aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorDavid Nusinow <[email protected]>2006-09-24 21:11:46 +0000
committerDavid Nusinow <[email protected]>2006-09-24 21:11:46 +0000
commiteadb76b3f8e0e9b82da762bd29e53895bf9e6351 (patch)
treeb9f68fc763f9ea055287c366e61de84191b200ce /src/mesa/drivers
parentb3f7313ae4f4cd418522595e90e7d06ef6992f0a (diff)
Bump to latest mesa in Debian
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/allegro/amesa.c404
-rw-r--r--src/mesa/drivers/allegro/direct.h189
-rw-r--r--src/mesa/drivers/allegro/generic.h234
-rw-r--r--src/mesa/drivers/d3d/D3DCAPS.CPP250
-rw-r--r--src/mesa/drivers/d3d/D3DHAL.H68
-rw-r--r--src/mesa/drivers/d3d/D3DInit.cpp891
-rw-r--r--src/mesa/drivers/d3d/D3DMESA.H84
-rw-r--r--src/mesa/drivers/d3d/D3DRaster.cpp213
-rw-r--r--src/mesa/drivers/d3d/D3DShared.h154
-rw-r--r--src/mesa/drivers/d3d/D3DTEXT.CPP576
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.cpp947
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.h62
-rw-r--r--src/mesa/drivers/d3d/D3DUTILS.CPP638
-rw-r--r--src/mesa/drivers/d3d/D3Dvbrender.c2149
-rw-r--r--src/mesa/drivers/d3d/DDrawPROCS.c399
-rw-r--r--src/mesa/drivers/d3d/DEBUG.C143
-rw-r--r--src/mesa/drivers/d3d/DEBUG.H90
-rw-r--r--src/mesa/drivers/d3d/DbgEnv.bat25
-rw-r--r--src/mesa/drivers/d3d/MAKEFILE101
-rw-r--r--src/mesa/drivers/d3d/NULLProcs.h49
-rw-r--r--src/mesa/drivers/d3d/NullProcs.c49
-rw-r--r--src/mesa/drivers/d3d/OPENGL32.DEF442
-rw-r--r--src/mesa/drivers/d3d/WGL.C1262
-rw-r--r--src/mesa/drivers/d3d/d3dText.h53
-rw-r--r--src/mesa/drivers/directfb/idirectfbgl_mesa.c8
-rw-r--r--src/mesa/drivers/dri/Makefile.template18
-rw-r--r--src/mesa/drivers/dri/common/glcontextmodes.c38
-rw-r--r--src/mesa/drivers/dri/common/texmem.c1
-rw-r--r--src/mesa/drivers/dri/common/utils.c15
-rw-r--r--src/mesa/drivers/dri/common/xmlpool/Makefile96
-rw-r--r--src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py191
-rw-r--r--src/mesa/drivers/dri/dri_client/Makefile60
-rw-r--r--src/mesa/drivers/dri/dri_client/imports/xf86drm.h636
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drm.c2333
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmHash.c433
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmRandom.c217
-rw-r--r--src/mesa/drivers/dri/dri_client/xf86drmSL.c488
-rw-r--r--src/mesa/drivers/dri/ffb/ffb_vtxfmt.c13
-rw-r--r--src/mesa/drivers/dri/i810/i810context.c1
-rw-r--r--src/mesa/drivers/dri/i810/i810state.c1
-rw-r--r--src/mesa/drivers/dri/i810/i810texstate.c166
-rw-r--r--src/mesa/drivers/dri/i915/Makefile3
-rw-r--r--src/mesa/drivers/dri/i915/i830_context.c2
-rw-r--r--src/mesa/drivers/dri/i915/i830_context.h2
-rw-r--r--src/mesa/drivers/dri/i915/i830_vtbl.c45
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.c2
-rw-r--r--src/mesa/drivers/dri/i915/i915_context.h1
-rw-r--r--src/mesa/drivers/dri/i915/i915_texprog.c21
-rw-r--r--src/mesa/drivers/dri/i915/i915_texstate.c4
-rw-r--r--src/mesa/drivers/dri/i915/intel_batchbuffer.c7
-rw-r--r--src/mesa/drivers/dri/i915/intel_batchbuffer.h5
-rw-r--r--src/mesa/drivers/dri/i915/intel_context.h2
-rw-r--r--src/mesa/drivers/dri/i915/intel_ioctl.c4
-rw-r--r--src/mesa/drivers/dri/i915/intel_pixel.c8
-rw-r--r--src/mesa/drivers/dri/i915/intel_screen.c2
-rw-r--r--src/mesa/drivers/dri/i915/intel_tex.c5
-rw-r--r--src/mesa/drivers/dri/i915/intel_tris.c2
-rw-r--r--src/mesa/drivers/dri/i915/server/intel.h44
-rw-r--r--src/mesa/drivers/dri/i915/server/intel_dri.c397
-rw-r--r--src/mesa/drivers/dri/mga/README26
-rw-r--r--src/mesa/drivers/dri/mga/mgaioctl.c4
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.c10
-rw-r--r--src/mesa/drivers/dri/r128/r128_context.h2
-rw-r--r--src/mesa/drivers/dri/r128/r128_lock.c2
-rw-r--r--src/mesa/drivers/dri/r128/r128_state.c12
-rw-r--r--src/mesa/drivers/dri/r128/r128_tris.c25
-rw-r--r--src/mesa/drivers/dri/r200/Makefile2
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.c10
-rw-r--r--src/mesa/drivers/dri/r200/r200_context.h2
-rw-r--r--src/mesa/drivers/dri/r200/r200_state.c10
-rw-r--r--src/mesa/drivers/dri/r200/r200_swtcl.c31
-rw-r--r--src/mesa/drivers/dri/r200/r200_vtxfmt.c16
-rw-r--r--src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S4
-rw-r--r--src/mesa/drivers/dri/r300/Makefile4
-rw-r--r--src/mesa/drivers/dri/r300/r300_cmdbuf.c23
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.c60
-rw-r--r--src/mesa/drivers/dri/r300/r300_context.h33
-rw-r--r--src/mesa/drivers/dri/r300/r300_fragprog.c2
-rw-r--r--src/mesa/drivers/dri/r300/r300_ioctl.c8
-rw-r--r--src/mesa/drivers/dri/r300/r300_maos.c133
-rw-r--r--src/mesa/drivers/dri/r300/r300_reg.h16
-rw-r--r--src/mesa/drivers/dri/r300/r300_render.c6
-rw-r--r--src/mesa/drivers/dri/r300/r300_state.c172
-rw-r--r--src/mesa/drivers/dri/r300/r300_texmem.c18
-rw-r--r--src/mesa/drivers/dri/r300/r300_vertexprog.c10
-rw-r--r--src/mesa/drivers/dri/r300/radeon_context.c2
-rw-r--r--src/mesa/drivers/dri/r300/radeon_span.c29
-rw-r--r--src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c87
-rw-r--r--src/mesa/drivers/dri/radeon/Makefile2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.c10
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_context.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.c84
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_screen.h2
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_state.c10
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_swtcl.c31
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxfmt.c13
-rw-r--r--src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S4
-rw-r--r--src/mesa/drivers/dri/radeon/server/radeon_dri.c1
-rw-r--r--src/mesa/drivers/dri/savage/savagestate.c8
-rw-r--r--src/mesa/drivers/dri/savage/savagetex.c148
-rw-r--r--src/mesa/drivers/dri/savage/savagetris.c42
-rw-r--r--src/mesa/drivers/dri/sis/sis_clear.c7
-rw-r--r--src/mesa/drivers/dri/sis/sis_context.h2
-rw-r--r--src/mesa/drivers/dri/sis/sis_state.c2
-rw-r--r--src/mesa/drivers/dri/sis/sis_stencil.c5
-rw-r--r--src/mesa/drivers/dri/sis/sis_tris.c19
-rw-r--r--src/mesa/drivers/dri/tdfx/BUGS64
-rw-r--r--src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S84
-rw-r--r--src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h314
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_render.c28
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_state.c6
-rw-r--r--src/mesa/drivers/dri/tdfx/tdfx_tex.c84
-rw-r--r--src/mesa/drivers/dri/unichrome/via_ioctl.c2
-rw-r--r--src/mesa/drivers/dri/unichrome/via_tex.c15
-rw-r--r--src/mesa/drivers/dri/unichrome/via_tris.c27
-rw-r--r--src/mesa/drivers/ggi/default/.cvsignore1
-rw-r--r--src/mesa/drivers/ggi/default/genkgi.h76
-rw-r--r--src/mesa/drivers/ggi/default/genkgi_mode.c2
-rw-r--r--src/mesa/drivers/ggi/default/genkgi_visual.c2
-rw-r--r--src/mesa/drivers/ggi/display/.cvsignore1
-rw-r--r--src/mesa/drivers/ggi/include/ggi/mesa/debug.h2
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c877
-rw-r--r--src/mesa/drivers/svga/svgamesa.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa15.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa15.h2
-rw-r--r--src/mesa/drivers/svga/svgamesa16.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa16.h2
-rw-r--r--src/mesa/drivers/svga/svgamesa24.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa24.h2
-rw-r--r--src/mesa/drivers/svga/svgamesa32.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa32.h2
-rw-r--r--src/mesa/drivers/svga/svgamesa8.c2
-rw-r--r--src/mesa/drivers/svga/svgamesa8.h2
-rw-r--r--src/mesa/drivers/svga/svgapix.h2
-rw-r--r--src/mesa/drivers/windows/fx/fx.rc39
-rw-r--r--src/mesa/drivers/windows/gdi/wgl.c2
-rw-r--r--src/mesa/drivers/windows/gdi/wmesa.c4
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c1196
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h292
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c346
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c1448
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c2196
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c257
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c423
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c1611
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c1176
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h324
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c344
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c1446
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c2046
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c249
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c449
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c1335
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c1206
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h327
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c344
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c1446
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c2104
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c263
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c444
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c1345
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_clip.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_norm.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_xform.c2
-rw-r--r--src/mesa/drivers/windows/gldirect/gldirect.rc43
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/colors.h523
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1719
-rw-r--r--src/mesa/drivers/windows/gldirect/opengl32.ref495
-rw-r--r--src/mesa/drivers/x11/xm_buffer.c4
-rw-r--r--src/mesa/drivers/x11/xm_dd.c34
-rw-r--r--src/mesa/drivers/x11/xm_line.c20
-rw-r--r--src/mesa/drivers/x11/xm_span.c271
-rw-r--r--src/mesa/drivers/x11/xm_tri.c36
-rw-r--r--src/mesa/drivers/x11/xmesaP.h12
180 files changed, 42657 insertions, 1133 deletions
diff --git a/src/mesa/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c
new file mode 100644
index 00000000000..cb46efa56ac
--- /dev/null
+++ b/src/mesa/drivers/allegro/amesa.c
@@ -0,0 +1,404 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.0
+ * Copyright (C) 1995-1998 Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <allegro.h>
+#include "buffers.h"
+#include "context.h"
+#include "imports.h"
+#include "matrix.h"
+#include "mtypes.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, GLframebuffer *buffer, GLuint bit)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ GLboolean ok = GL_TRUE;
+
+ if (bit == DD_FRONT_LEFT_BIT)
+ context->Buffer->Active = context->Buffer->Screen;
+
+ else if (bit == DD_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 viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
+{
+ /* poll for window size change and realloc software Z/stencil/etc if needed */
+ _mesa_ResizeBuffersMESA();
+}
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+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.Viewport = viewport;
+
+ 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 = _mesa_create_visual(GL_TRUE, /* rgb mode */
+ dbFlag, /* db_flag */
+ GL_FALSE, /* stereo */
+ redBits, greenBits, blueBits, 8,
+ 0, /* index bits */
+ depthSize, /* depth bits */
+ stencilSize,/* stencil bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ accumSize, /* accum bits */
+ 1 );
+ if (!visual->GLVisual)
+ {
+ free(visual);
+ return NULL;
+ }
+
+ return visual;
+ }
+
+
+void AMesaDestroyVisual(AMesaVisual visual)
+ {
+ _mesa_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 = _mesa_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);
+ _mesa_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 = _mesa_create_context(visual->GLVisual,
+ share ? share->GLContext : NULL,
+ (void *) context, GL_FALSE );
+ if (!context->GLContext)
+ {
+ free(context);
+ return NULL;
+ }
+
+ return context;
+}
+
+
+void AMesaDestroyContext(AMesaContext context)
+{
+ _mesa_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);
+ _mesa_make_current(context->GLContext, buffer->GLBuffer);
+ }
+ else {
+ /* XXX I don't think you want to destroy anything here! */
+ destroy_bitmap(context->Buffer->Screen);
+ context->Buffer->Screen = NULL;
+ context->Buffer->Active = NULL;
+ context->Buffer = NULL;
+ _mesa_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 00000000000..3998fc19d7b
--- /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 00000000000..cbdf5ff2b3a
--- /dev/null
+++ b/src/mesa/drivers/allegro/generic.h
@@ -0,0 +1,234 @@
+/*
+ * 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, const GLfloat color[4])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ GLubyte r, g, b;
+ CLAMPED_FLOAT_TO_UBYTE(r, color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(g, color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(b, color[2]);
+ context->ClearColor = makecol(r, g, b);
+ }
+
+
+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/d3d/D3DCAPS.CPP b/src/mesa/drivers/d3d/D3DCAPS.CPP
new file mode 100644
index 00000000000..cd95ef0f1ee
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DCAPS.CPP
@@ -0,0 +1,250 @@
+/*===========================================================================*/
+/* */
+/* 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;
+ }
+ }
+}
+
diff --git a/src/mesa/drivers/d3d/D3DHAL.H b/src/mesa/drivers/d3d/D3DHAL.H
new file mode 100644
index 00000000000..5295520d7be
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DHAL.H
@@ -0,0 +1,68 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _D3D_HAL_INC
+#define _D3D_HAL_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <time.h>
+#include "D3DShared.h"
+#include "D3DTextureMgr.h"
+#include "Debug.h"
+/*===========================================================================*/
+/* Defines. */
+/*===========================================================================*/
+#define DX_RESTORE(ps) if ( (ps) && (ps)->IsLost() ) (ps)->Restore();
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _d3d_hal_struct
+{
+ MESAD3DSHARED shared;
+
+ GUID guid;
+ LPDIRECTDRAW lpDD;
+ LPDIRECTDRAW4 lpDD4;
+ LPDIRECT3D3 lpD3D3;
+ LPDIRECT3DDEVICE3 lpD3DDevice;
+ D3DDEVICEDESC D3DHWDevDesc;
+ LPDIRECTDRAWSURFACE4 lpDDSPrimary,
+ lpDDSRender,
+ lpDDSZbuffer;
+ LPDIRECT3DVIEWPORT3 lpViewport;
+ LPDIRECTDRAWCLIPPER lpClipper;
+ DDPIXELFORMAT ddpf,
+ ddpfZBuffer;
+ PTM_OBJECT pTMList;
+
+} MESAD3DHAL, *PMESAD3DHAL;
+/*===========================================================================*/
+/* External function prototypes. */
+/*===========================================================================*/
+extern BOOL InitTMgrHAL( PMESAD3DHAL pHAL );
+extern void TermTMgrHAL( PMESAD3DHAL pHAL );
+extern void AlphaBlendTableHAL( PMESAD3DHAL pHAL );
+
+extern void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel );
+extern char *ErrorStringD3D( HRESULT hr );
+extern void FatalShutDown( PMESAD3DHAL pHAL );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern char *errorMsg;
+
+#endif
+
diff --git a/src/mesa/drivers/d3d/D3DInit.cpp b/src/mesa/drivers/d3d/D3DInit.cpp
new file mode 100644
index 00000000000..ba7891612e4
--- /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 00000000000..074ceca816a
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DMESA.H
@@ -0,0 +1,84 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef D3D_MESA_H
+#define D3D_MESA_H
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "matrix.h"
+#include "context.h"
+#include "mtypes.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
+
diff --git a/src/mesa/drivers/d3d/D3DRaster.cpp b/src/mesa/drivers/d3d/D3DRaster.cpp
new file mode 100644
index 00000000000..004bb773603
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DRaster.cpp
@@ -0,0 +1,213 @@
+/*===========================================================================*/
+/* */
+/* 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
+}
+
+
+
+
+
+
+
+
diff --git a/src/mesa/drivers/d3d/D3DShared.h b/src/mesa/drivers/d3d/D3DShared.h
new file mode 100644
index 00000000000..cc629e21111
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DShared.h
@@ -0,0 +1,154 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef D3D_MESA_ALL_H
+#define D3D_MESA_ALL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <stdio.h>
+#include <string.h>
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+#define TM_ACTION_LOAD 0x01
+#define TM_ACTION_BIND 0x02
+#define TM_ACTION_UPDATE 0x04
+
+#define UM_FATALSHUTDOWN (WM_USER+42)
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+#define ALLOC(cb) malloc( (cb) )
+#define FREE(p) { free( (p) ); (p) = NULL; }
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _pixel_convert
+{
+ int cb, /* Count in bytes of one pixel. */
+ rShift, /* Shift count that postions each componet. */
+ gShift,
+ bShift,
+ aShift;
+ float rScale, /* Value that scales a color that ranges 0.0 -> 1.0 */
+ gScale, /* to this pixel format. */
+ bScale,
+ aScale;
+ DWORD dwRMask, /* Color mask per component. */
+ dwGMask,
+ dwBMask,
+ dwAMask;
+
+} PIXELINFO, *PPIXELINFO;
+
+
+typedef struct _d3d_shared_info
+{
+ HWND hwnd;
+ BOOL bWindow,
+ bFlipable,
+ bForceSW,
+ bHardware;
+ RECT rectW, /* Window size and postion in screen space. */
+ rectV; /* Viewport size and postion. */
+ DWORD dwWidth, /* Current render size for quick checks. */
+ dwHeight;
+
+ PIXELINFO pixel;
+ DWORD dwSrcBlendCaps[14], /* See D3DCAPS.CPP */
+ dwDestBlendCaps[14],
+ dwTexFunc[4];
+
+} MESAD3DSHARED, *PMESAD3DSHARED;
+
+typedef struct _render_options
+{
+ BOOL bForceSoftware, /* TODO: Add user switches. */
+ bStretchtoPrimary;
+
+} USER_CTRL, *PUSER_CRTL;
+
+enum { s_zero = 0,
+ s_one,
+ s_dst_color,
+ s_one_minus_dst_color,
+ s_src_alpha,
+ s_one_minus_src_alpha,
+ s_dst_alpha,
+ s_one_minus_dst_alpha,
+ s_src_alpha_saturate,
+ s_constant_color,
+ s_one_minus_constant_color,
+ s_constant_alpha,
+ s_one_minus_constant_alpha };
+
+enum { d_zero = 0,
+ d_one,
+ d_src_color,
+ d_one_minus_src_color,
+ d_src_alpha,
+ d_one_minus_src_alpha,
+ d_dst_alpha,
+ d_one_minus_dst_alpha,
+ d_constant_color,
+ d_one_minus_constant_color,
+ d_constant_alpha,
+ d_one_minus_constant_alpha };
+
+enum { d3dtblend_decal = 0,
+ d3dtblend_decalalpha,
+ d3dtblend_modulate,
+ d3dtblend_modulatealpha };
+
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+PMESAD3DSHARED InitHAL( HWND hwnd );
+void TermHAL( PMESAD3DSHARED pShared );
+BOOL CreateHAL( PMESAD3DSHARED pShared );
+BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ );
+
+void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil );
+void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState );
+void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount );
+
+void SwapBuffersHAL( PMESAD3DSHARED pShared );
+DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack );
+void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack );
+void UpdateScreenPosHAL( PMESAD3DSHARED pShared );
+void GetPixelInfoHAL( PMESAD3DSHARED pShared, PPIXELINFO pPixel );
+BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels );
+void DisableTMgrHAL( PMESAD3DSHARED pShared );
+
+
+int SaveDIBitmap( char *filename, BITMAPINFO *info, void *bits );
+int ARGB_SaveBitmap( char *filename, int width, int height, unsigned char *pARGB );
+int BGRA_SaveBitmap( char *filename, int width, int height, unsigned char *pBGRA );
+int BGR_SaveBitmap( char *filename, int width, int height, unsigned char *pBGR );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern float g_DepthScale, /* Mesa needs to scale Z in SW. The HAL */
+ g_MaxDepth; /* doesn't but I wanted SW still to work.*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/mesa/drivers/d3d/D3DTEXT.CPP b/src/mesa/drivers/d3d/D3DTEXT.CPP
new file mode 100644
index 00000000000..e6ff8645611
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTEXT.CPP
@@ -0,0 +1,576 @@
+/*===========================================================================*/
+/* */
+/* 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
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.cpp b/src/mesa/drivers/d3d/D3DTextureMgr.cpp
new file mode 100644
index 00000000000..ac9d2621fcc
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTextureMgr.cpp
@@ -0,0 +1,947 @@
+/*===========================================================================*/
+/* */
+/* 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;
+}
+
+
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.h b/src/mesa/drivers/d3d/D3DTextureMgr.h
new file mode 100644
index 00000000000..f4a4154917a
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTextureMgr.h
@@ -0,0 +1,62 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _TEXTURE_MGR_INC
+#define _TEXTURE_MGR_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include "GL/gl.h"
+/*========================================================================*/
+/* Defines. */
+/*========================================================================*/
+/*========================================================================*/
+/* Type defines. */
+/*========================================================================*/
+typedef struct _local_texture_object
+{
+ DWORD dwName,
+ dwPriority,
+ dwFlags,
+ dwSWidth,
+ dwSHeight,
+ dwVWidth,
+ dwVHeight;
+ BOOL bLock,
+ bDirty; /* I only update VID on SubImage calls so the system */
+ /* texture can get invalid. */
+
+ LPDIRECT3DDEVICE3 lpD3DDevice; /* If the device changes we must get new handles... */
+ LPDIRECTDRAWSURFACE4 lpDDS_System,
+ lpDDS_Video;
+ LPDIRECT3DTEXTURE2 lpD3DTexture2;
+
+ PIXELINFO pixel;
+
+ struct _local_texture_object *next;
+ struct _local_texture_object *prev;
+
+} TM_OBJECT, *PTM_OBJECT;
+/*========================================================================*/
+/* Function prototypes. */
+/*========================================================================*/
+void APIENTRY InitTMD3D( void *pVoid );
+void APIENTRY TermTMD3D( void *pVoid );
+/*========================================================================*/
+/* Global variables declaration. */
+/*========================================================================*/
+
+#endif
diff --git a/src/mesa/drivers/d3d/D3DUTILS.CPP b/src/mesa/drivers/d3d/D3DUTILS.CPP
new file mode 100644
index 00000000000..c13d89cd711
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DUTILS.CPP
@@ -0,0 +1,638 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local only functions. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask );
+/*===========================================================================*/
+/* This function is used to get the pointer to the surface and the pitch for*/
+/* the scanline rendering functions. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ static DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LockHAL();" ));
+
+ /* Set the request structure up first. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Lock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+
+ return &ddsd2;
+}
+/*===========================================================================*/
+/* This is just a simple wrapper. I probably don't need to do any error */
+/* checking as the Lock must have worked inorder to get here... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "UnlockHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Unlock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+}
+/*===========================================================================*/
+/* This function will track the main/Primary window that will be used as the*/
+/* target for the Blt in SwapBuffers. As a side effect the call will check */
+/* to see if the primary surface is the same size and position as the screen.*/
+/* If they are the same size we will call it fullscreen... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UpdateScreenPosHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ POINT pt;
+ DWORD dwWidth, dwHeight;
+
+ DPF(( DBG_FUNC, "UpdateScreenPosHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL != NULL )
+ {
+ /* Update the windows screen position. */
+ GetClientRect( pShared->hwnd, &pShared->rectW );
+ pt.x = pt.y = 0;
+ ClientToScreen( pShared->hwnd, &pt );
+ OffsetRect( &pShared->rectW, pt.x, pt.y);
+
+ /* Compare the primary to the screen. */
+ dwWidth = GetSystemMetrics( SM_CXSCREEN );
+ dwHeight = GetSystemMetrics( SM_CYSCREEN );
+ if ( (pShared->rectW.left > 0) || (pShared->rectW.top > 0) ||
+ (pShared->rectW.right > dwWidth) || (pShared->rectW.bottom > dwHeight) )
+ pShared->bWindow = TRUE;
+ else
+ pShared->bWindow = FALSE;
+ }
+}
+/*===========================================================================*/
+/* This function will fill in the pixel info structure defined in D3Dshared.*/
+/* Basicly it will take a DirectDraw pixelformat structure and make scaling */
+/* values that will convert from 8bit channels to whatever the supplied ddpf */
+/* uses. Also we will generate shift values that will be used to get move */
+/* each component of the pixel into place. */
+/* I have now added a special case for a 1bit alpha channel. If I find a 1b*/
+/* alpha then I will set the scale to -1.0 which should be unique. Later I */
+/* can check the alpha scale value too see if its -1.0 and thus handle it. I*/
+/* was finding that the case was not working tom my advantage so this is my */
+/* HACK for the day. As a TODO I should work on this... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel )
+{
+ DPF(( DBG_FUNC, "Solve8BitChannelPixelFromat();" ));
+
+ memset( pPixel, 0, sizeof(PPIXELINFO) );
+
+ /* Check too see if the color space is valid in the PF. */
+ if ( pddpf->dwFlags & DDPF_RGB )
+ {
+ /* Solve the red stuff. */
+ pPixel->dwRMask = pddpf->dwRBitMask;
+ pPixel->rShift = CountTrailingZeros( pPixel->dwRMask );
+ pPixel->rScale = (float)0.00392156 * (float)(pPixel->dwRMask >> pPixel->rShift);
+
+ /* Solve the green thingy's. */
+ pPixel->dwGMask = pddpf->dwGBitMask;
+ pPixel->gShift = CountTrailingZeros( pPixel->dwGMask );
+ pPixel->gScale = (float)0.00392156 * (float)(pPixel->dwGMask >> pPixel->gShift);
+
+ /* Solve the blues. */
+ pPixel->dwBMask = pddpf->dwBBitMask;
+ pPixel->bShift = CountTrailingZeros( pddpf->dwBBitMask );
+ pPixel->bScale = (float)0.00392156 * (float)(pddpf->dwBBitMask >> pPixel->bShift);
+ }
+
+ /* Do the alpha channel if there is one. */
+ if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ pPixel->dwAMask = pddpf->dwRGBAlphaBitMask;
+ pPixel->aShift = CountTrailingZeros( pPixel->dwAMask );
+
+ /* Special case a 1bit alpha. */
+ if ( (pPixel->dwAMask >> pPixel->aShift) == 1 )
+ pPixel->aScale = -1.0;
+ else
+ pPixel->aScale = (float)0.00392156 * (float)(pPixel->dwAMask >> pPixel->aShift);
+ }
+
+ /* Get the size of the pixel in bytes. Should work as dwRGBBitCount is in a union. */
+ pPixel->cb = pddpf->dwRGBBitCount / 8;
+}
+/*===========================================================================*/
+/* See RETURN :) */
+/*===========================================================================*/
+/* RETURN: number of contiguous zeros starting from the right. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask )
+{
+ DWORD Mask;
+
+ if ( dwMask == 0 )
+ return 32;
+
+ /* Can't take credit for this one! */
+ Mask = dwMask & -(int)dwMask;
+ return ((Mask & 0xFFFF0000)!=0) << 4
+ | ((Mask & 0xFF00FF00)!=0) << 3
+ | ((Mask & 0xF0F0F0F0)!=0) << 2
+ | ((Mask & 0xCCCCCCCC)!=0) << 1
+ | ((Mask & 0xAAAAAAAA)!=0);
+}
+/*===========================================================================*/
+/* This function will convert the DDraw error code to its macro string. The*/
+/* returned pointer is static so you need not worry about memory managemnet */
+/* but the error message gets written over from call to call... */
+/*===========================================================================*/
+/* RETURN: pointer to the single static buffer that hold the error message. */
+/*===========================================================================*/
+char *ErrorStringD3D( HRESULT hr )
+{
+ static char errorString[128];
+
+ switch( hr )
+ {
+ case DDERR_ALREADYINITIALIZED:
+ strcpy( errorString, "DDERR_ALREADYINITIALIZED" );
+ break;
+
+ case DDERR_CANNOTATTACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTATTACHSURFACE" );
+ break;
+
+ case DDERR_CANNOTDETACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTDETACHSURFACE" );
+ break;
+
+ case DDERR_CURRENTLYNOTAVAIL:
+ strcpy( errorString, "DDERR_CURRENTLYNOTAVAIL" );
+ break;
+
+ case DDERR_EXCEPTION:
+ strcpy( errorString, "DDERR_EXCEPTION" );
+ break;
+
+ case DDERR_GENERIC:
+ strcpy( errorString, "DDERR_GENERIC" );
+ break;
+
+ case DDERR_HEIGHTALIGN:
+ strcpy( errorString, "DDERR_HEIGHTALIGN" );
+ break;
+
+ case DDERR_INCOMPATIBLEPRIMARY:
+ strcpy( errorString, "DDERR_INCOMPATIBLEPRIMARY" );
+ break;
+
+ case DDERR_INVALIDCAPS:
+ strcpy( errorString, "DDERR_INVALIDCAPS" );
+ break;
+
+ case DDERR_INVALIDCLIPLIST:
+ strcpy( errorString, "DDERR_INVALIDCLIPLIST" );
+ break;
+
+ case DDERR_INVALIDMODE:
+ strcpy( errorString, "DDERR_INVALIDMODE" );
+ break;
+
+ case DDERR_INVALIDOBJECT:
+ strcpy( errorString, "DDERR_INVALIDOBJECT" );
+ break;
+
+ case DDERR_INVALIDPARAMS:
+ strcpy( errorString, "DDERR_INVALIDPARAMS" );
+ break;
+
+ case DDERR_INVALIDPIXELFORMAT:
+ strcpy( errorString, "DDERR_INVALIDPIXELFORMAT" );
+ break;
+
+ case DDERR_INVALIDRECT:
+ strcpy( errorString, "DDERR_INVALIDRECT" );
+ break;
+
+ case DDERR_LOCKEDSURFACES:
+ strcpy( errorString, "DDERR_LOCKEDSURFACES" );
+ break;
+
+ case DDERR_NO3D:
+ strcpy( errorString, "DDERR_NO3D" );
+ break;
+
+ case DDERR_NOALPHAHW:
+ strcpy( errorString, "DDERR_NOALPHAHW" );
+ break;
+
+ case DDERR_NOCLIPLIST:
+ strcpy( errorString, "DDERR_NOCLIPLIST" );
+ break;
+
+ case DDERR_NOCOLORCONVHW:
+ strcpy( errorString, "DDERR_NOCOLORCONVHW" );
+ break;
+
+ case DDERR_NOCOOPERATIVELEVELSET:
+ strcpy( errorString, "DDERR_NOCOOPERATIVELEVELSET" );
+ break;
+
+ case DDERR_NOCOLORKEY:
+ strcpy( errorString, "DDERR_NOCOLORKEY" );
+ break;
+
+ case DDERR_NOCOLORKEYHW:
+ strcpy( errorString, "DDERR_NOCOLORKEYHW" );
+ break;
+
+ case DDERR_NODIRECTDRAWSUPPORT:
+ strcpy( errorString, "DDERR_NODIRECTDRAWSUPPORT" );
+ break;
+
+ case DDERR_NOEXCLUSIVEMODE:
+ strcpy( errorString, "DDERR_NOEXCLUSIVEMODE" );
+ break;
+
+ case DDERR_NOFLIPHW:
+ strcpy( errorString, "DDERR_NOFLIPHW" );
+ break;
+
+ case DDERR_NOGDI:
+ strcpy( errorString, "DDERR_NOGDI" );
+ break;
+
+ case DDERR_NOMIRRORHW:
+ strcpy( errorString, "DDERR_NOMIRRORHW" );
+ break;
+
+ case DDERR_NOTFOUND:
+ strcpy( errorString, "DDERR_NOTFOUND" );
+ break;
+
+ case DDERR_NOOVERLAYHW:
+ strcpy( errorString, "DDERR_NOOVERLAYHW" );
+ break;
+
+ case DDERR_OVERLAPPINGRECTS:
+ strcpy( errorString, "DDERR_OVERLAPPINGRECTS" );
+ break;
+
+ case DDERR_NORASTEROPHW:
+ strcpy( errorString, "DDERR_NORASTEROPHW" );
+ break;
+
+ case DDERR_NOROTATIONHW:
+ strcpy( errorString, "DDERR_NOROTATIONHW" );
+ break;
+
+ case DDERR_NOSTRETCHHW:
+ strcpy( errorString, "DDERR_NOSTRETCHHW" );
+ break;
+
+ case DDERR_NOT4BITCOLOR:
+ strcpy( errorString, "DDERR_NOT4BITCOLOR" );
+ break;
+
+ case DDERR_NOT4BITCOLORINDEX:
+ strcpy( errorString, "DDERR_NOT4BITCOLORINDEX" );
+ break;
+
+ case DDERR_NOT8BITCOLOR:
+ strcpy( errorString, "DDERR_NOT8BITCOLOR" );
+ break;
+
+ case DDERR_NOTEXTUREHW:
+ strcpy( errorString, "DDERR_NOTEXTUREHW" );
+ break;
+
+ case DDERR_NOVSYNCHW:
+ strcpy( errorString, "DDERR_NOVSYNCHW" );
+ break;
+
+ case DDERR_NOZBUFFERHW:
+ strcpy( errorString, "DDERR_NOZBUFFERHW" );
+ break;
+
+ case DDERR_NOZOVERLAYHW:
+ strcpy( errorString, "DDERR_NOZOVERLAYHW" );
+ break;
+
+ case DDERR_OUTOFCAPS:
+ strcpy( errorString, "DDERR_OUTOFCAPS" );
+ break;
+
+ case DDERR_OUTOFMEMORY:
+ strcpy( errorString, "DDERR_OUTOFMEMORY" );
+ break;
+
+ case DDERR_OUTOFVIDEOMEMORY:
+ strcpy( errorString, "DDERR_OUTOFVIDEOMEMORY" );
+ break;
+
+ case DDERR_OVERLAYCANTCLIP:
+ strcpy( errorString, "DDERR_OVERLAYCANTCLIP" );
+ break;
+
+ case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
+ strcpy( errorString, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE" );
+ break;
+
+ case DDERR_PALETTEBUSY:
+ strcpy( errorString, "DDERR_PALETTEBUSY" );
+ break;
+
+ case DDERR_COLORKEYNOTSET:
+ strcpy( errorString, "DDERR_COLORKEYNOTSET" );
+ break;
+
+ case DDERR_SURFACEALREADYATTACHED:
+ strcpy( errorString, "DDERR_SURFACEALREADYATTACHED" );
+ break;
+
+ case DDERR_SURFACEALREADYDEPENDENT:
+ strcpy( errorString, "DDERR_SURFACEALREADYDEPENDENT" );
+ break;
+
+ case DDERR_SURFACEBUSY:
+ strcpy( errorString, "DDERR_SURFACEBUSY" );
+ break;
+
+ case DDERR_CANTLOCKSURFACE:
+ strcpy( errorString, "DDERR_CANTLOCKSURFACE" );
+ break;
+
+ case DDERR_SURFACEISOBSCURED:
+ strcpy( errorString, "DDERR_SURFACEISOBSCURED" );
+ break;
+
+ case DDERR_SURFACELOST:
+ strcpy( errorString, "DDERR_SURFACELOST" );
+ break;
+
+ case DDERR_SURFACENOTATTACHED:
+ strcpy( errorString, "DDERR_SURFACENOTATTACHED" );
+ break;
+
+ case DDERR_TOOBIGHEIGHT:
+ strcpy( errorString, "DDERR_TOOBIGHEIGHT" );
+ break;
+
+ case DDERR_TOOBIGSIZE:
+ strcpy( errorString, "DDERR_TOOBIGSIZE" );
+ break;
+
+ case DDERR_TOOBIGWIDTH:
+ strcpy( errorString, "DDERR_TOOBIGWIDTH" );
+ break;
+
+ case DDERR_UNSUPPORTED:
+ strcpy( errorString, "DDERR_UNSUPPORTED" );
+ break;
+
+ case DDERR_UNSUPPORTEDFORMAT:
+ strcpy( errorString, "DDERR_UNSUPPORTEDFORMAT" );
+ break;
+
+ case DDERR_UNSUPPORTEDMASK:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMASK" );
+ break;
+
+ case DDERR_INVALIDSTREAM:
+ strcpy( errorString, "DDERR_INVALIDSTREAM" );
+ break;
+
+ case DDERR_VERTICALBLANKINPROGRESS:
+ strcpy( errorString, "DDERR_VERTICALBLANKINPROGRESS" );
+ break;
+
+ case DDERR_WASSTILLDRAWING:
+ strcpy( errorString, "DDERR_WASSTILLDRAWING" );
+ break;
+
+ case DDERR_XALIGN:
+ strcpy( errorString, "DDERR_XALIGN" );
+ break;
+
+ case DDERR_INVALIDDIRECTDRAWGUID:
+ strcpy( errorString, "DDERR_INVALIDDIRECTDRAWGUID" );
+ break;
+
+ case DDERR_DIRECTDRAWALREADYCREATED:
+ strcpy( errorString, "DDERR_DIRECTDRAWALREADYCREATED" );
+ break;
+
+ case DDERR_NODIRECTDRAWHW:
+ strcpy( errorString, "DDERR_NODIRECTDRAWHW" );
+ break;
+
+ case DDERR_PRIMARYSURFACEALREADYEXISTS:
+ strcpy( errorString, "DDERR_PRIMARYSURFACEALREADYEXISTS" );
+ break;
+
+ case DDERR_NOEMULATION:
+ strcpy( errorString, "DDERR_NOEMULATION" );
+ break;
+
+ case DDERR_REGIONTOOSMALL:
+ strcpy( errorString, "DDERR_REGIONTOOSMALL" );
+ break;
+
+ case DDERR_CLIPPERISUSINGHWND:
+ strcpy( errorString, "DDERR_CLIPPERISUSINGHWND" );
+ break;
+
+ case DDERR_NOCLIPPERATTACHED:
+ strcpy( errorString, "DDERR_NOCLIPPERATTACHED" );
+ break;
+
+ case DDERR_NOHWND:
+ strcpy( errorString, "DDERR_NOHWND" );
+ break;
+
+ case DDERR_HWNDSUBCLASSED:
+ strcpy( errorString, "DDERR_HWNDSUBCLASSED" );
+ break;
+
+ case DDERR_HWNDALREADYSET:
+ strcpy( errorString, "DDERR_HWNDALREADYSET" );
+ break;
+
+ case DDERR_NOPALETTEATTACHED:
+ strcpy( errorString, "DDERR_NOPALETTEATTACHED" );
+ break;
+
+ case DDERR_NOPALETTEHW:
+ strcpy( errorString, "DDERR_NOPALETTEHW" );
+ break;
+
+ case DDERR_BLTFASTCANTCLIP:
+ strcpy( errorString, "DDERR_BLTFASTCANTCLIP" );
+ break;
+
+ case DDERR_NOBLTHW:
+ strcpy( errorString, "DDERR_NOBLTHW" );
+ break;
+
+ case DDERR_NODDROPSHW:
+ strcpy( errorString, "DDERR_NODDROPSHW" );
+ break;
+
+ case DDERR_OVERLAYNOTVISIBLE:
+ strcpy( errorString, "DDERR_OVERLAYNOTVISIBLE" );
+ break;
+
+ case DDERR_NOOVERLAYDEST:
+ strcpy( errorString, "DDERR_NOOVERLAYDEST" );
+ break;
+
+ case DDERR_INVALIDPOSITION:
+ strcpy( errorString, "DDERR_INVALIDPOSITION" );
+ break;
+
+ case DDERR_NOTAOVERLAYSURFACE:
+ strcpy( errorString, "DDERR_NOTAOVERLAYSURFACE" );
+ break;
+
+ case DDERR_EXCLUSIVEMODEALREADYSET:
+ strcpy( errorString, "DDERR_EXCLUSIVEMODEALREADYSET" );
+ break;
+
+ case DDERR_NOTFLIPPABLE:
+ strcpy( errorString, "DDERR_NOTFLIPPABLE" );
+ break;
+
+ case DDERR_CANTDUPLICATE:
+ strcpy( errorString, "DDERR_CANTDUPLICATE" );
+ break;
+
+ case DDERR_NOTLOCKED:
+ strcpy( errorString, "DDERR_NOTLOCKED" );
+ break;
+
+ case DDERR_CANTCREATEDC:
+ strcpy( errorString, "DDERR_CANTCREATEDC" );
+ break;
+
+ case DDERR_NODC:
+ strcpy( errorString, "DDERR_NODC" );
+ break;
+
+ case DDERR_WRONGMODE:
+ strcpy( errorString, "DDERR_WRONGMODE" );
+ break;
+
+ case DDERR_IMPLICITLYCREATED:
+ strcpy( errorString, "DDERR_IMPLICITLYCREATED" );
+ break;
+
+ case DDERR_NOTPALETTIZED:
+ strcpy( errorString, "DDERR_NOTPALETTIZED" );
+ break;
+
+ case DDERR_UNSUPPORTEDMODE:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMODE" );
+ break;
+
+ case DDERR_NOMIPMAPHW:
+ strcpy( errorString, "DDERR_NOMIPMAPHW" );
+ break;
+
+ case DDERR_INVALIDSURFACETYPE:
+ strcpy( errorString, "DDERR_INVALIDSURFACETYPE" );
+ break;
+
+ case DDERR_NOOPTIMIZEHW:
+ strcpy( errorString, "DDERR_NOOPTIMIZEHW" );
+ break;
+
+ case DDERR_NOTLOADED:
+ strcpy( errorString, "DDERR_NOTLOADED" );
+ break;
+
+ case DDERR_NOFOCUSWINDOW:
+ strcpy( errorString, "DDERR_NOFOCUSWINDOW" );
+ break;
+
+ case DDERR_DCALREADYCREATED:
+ strcpy( errorString, "DDERR_DCALREADYCREATED" );
+ break;
+
+ case DDERR_NONONLOCALVIDMEM:
+ strcpy( errorString, "DDERR_NONONLOCALVIDMEM" );
+ break;
+
+ case DDERR_CANTPAGELOCK:
+ strcpy( errorString, "DDERR_CANTPAGELOCK" );
+ break;
+
+ case DDERR_CANTPAGEUNLOCK:
+ strcpy( errorString, "DDERR_CANTPAGEUNLOCK" );
+ break;
+
+ case DDERR_NOTPAGELOCKED:
+ strcpy( errorString, "DDERR_NOTPAGELOCKED" );
+ break;
+
+ case DDERR_MOREDATA:
+ strcpy( errorString, "DDERR_MOREDATA" );
+ break;
+
+ case DDERR_EXPIRED:
+ strcpy( errorString, "DDERR_EXPIRED" );
+ break;
+
+ case DDERR_VIDEONOTACTIVE:
+ strcpy( errorString, "DDERR_VIDEONOTACTIVE" );
+ break;
+
+ case DDERR_DEVICEDOESNTOWNSURFACE:
+ strcpy( errorString, "DDERR_DEVICEDOESNTOWNSURFACE" );
+ break;
+
+ case DDERR_NOTINITIALIZED:
+ strcpy( errorString, "DDERR_NOTINITIALIZED" );
+ break;
+
+ default:
+ strcpy( errorString, "<unknown error code>" );
+ break;
+ }
+
+ return &errorString[0];
+}
diff --git a/src/mesa/drivers/d3d/D3Dvbrender.c b/src/mesa/drivers/d3d/D3Dvbrender.c
new file mode 100644
index 00000000000..09857f1dc8d
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3Dvbrender.c
@@ -0,0 +1,2149 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include <stdio.h>
+#include "clip.h"
+#include "context.h"
+#include "light.h"
+#include "lines.h"
+#include "macros.h"
+#include "matrix.h"
+#include "pb.h"
+#include "points.h"
+#include "mtypes.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 */
+ _mesa_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 ( !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 ( !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 ( !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 ( !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._EnabledUnits )
+ {
+ switch( ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode )
+ {
+ case GL_MODULATE:
+ if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][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][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][0]->Format,
+ (RECT *)NULL,
+ ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Width,
+ ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][0]->Height,
+ TM_ACTION_BIND,
+ (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0][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._EnabledUnits )
+ {
+ texture = ctx->Texture._EnabledUnits;
+ 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][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 00000000000..a02a89debbb
--- /dev/null
+++ b/src/mesa/drivers/d3d/DDrawPROCS.c
@@ -0,0 +1,399 @@
+/*===========================================================================*/
+/* */
+/* 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 );
+}
diff --git a/src/mesa/drivers/d3d/DEBUG.C b/src/mesa/drivers/d3d/DEBUG.C
new file mode 100644
index 00000000000..dfa524bf314
--- /dev/null
+++ b/src/mesa/drivers/d3d/DEBUG.C
@@ -0,0 +1,143 @@
+/*===========================================================================*/
+/* */
+/* 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 ));
+}
+
+
+
+
+
diff --git a/src/mesa/drivers/d3d/DEBUG.H b/src/mesa/drivers/d3d/DEBUG.H
new file mode 100644
index 00000000000..76122b91210
--- /dev/null
+++ b/src/mesa/drivers/d3d/DEBUG.H
@@ -0,0 +1,90 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <stdio.h>
+#include <string.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "D3DShared.h"
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+#define DBG_FUNC 0x00000001
+#define DBG_STATES 0x00000002
+
+#define DBG_CNTX_INFO 0x00000010
+#define DBG_CNTX_WARN 0x00000020
+#define DBG_CNTX_PROFILE 0x00000040
+#define DBG_CNTX_ERROR 0x00000080
+#define DBG_CNTX_ALL 0x000000F0
+
+#define DBG_PRIM_INFO 0x00000100
+#define DBG_PRIM_WARN 0x00000200
+#define DBG_PRIM_PROFILE 0x00000400
+#define DBG_PRIM_ERROR 0x00000800
+#define DBG_PRIM_ALL 0x00000F00
+
+#define DBG_TXT_INFO 0x00001000
+#define DBG_TXT_WARN 0x00002000
+#define DBG_TXT_PROFILE 0x00004000
+#define DBG_TXT_ERROR 0x00008000
+#define DBG_TXT_ALL 0x0000F000
+
+#define DBG_ALL_INFO 0x11111110
+#define DBG_ALL_WARN 0x22222220
+#define DBG_ALL_PROFILE 0x44444440
+#define DBG_ALL_ERROR 0x88888880
+#define DBG_ALL 0xFFFFFFFF
+
+#ifdef D3D_DEBUG
+# define DPF(arg) DebugPrint arg
+# define RIP(pH,msg,err) OutputDebugString(msg); \
+ OutputDebugString(err); \
+ OutputDebugString("\n"); \
+ FatalShutDown(pH)
+#else
+# define DPF(arg)
+# define RIP(pH,msg,err) FatalShutDown(pH)
+#endif
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+extern void ReadDBGEnv( void );
+extern void _cdecl DebugPrint( int mask, char *pszFormat, ... );
+extern void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern DWORD g_DBGMask;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/mesa/drivers/d3d/DbgEnv.bat b/src/mesa/drivers/d3d/DbgEnv.bat
new file mode 100644
index 00000000000..40858e66844
--- /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 00000000000..ad1d40dc27b
--- /dev/null
+++ b/src/mesa/drivers/d3d/MAKEFILE
@@ -0,0 +1,101 @@
+##############################################################################
+#
+# 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:
+
+
+
+
diff --git a/src/mesa/drivers/d3d/NULLProcs.h b/src/mesa/drivers/d3d/NULLProcs.h
new file mode 100644
index 00000000000..f0bbd2162dd
--- /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 00000000000..d6fb598074b
--- /dev/null
+++ b/src/mesa/drivers/d3d/NullProcs.c
@@ -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 "mtypes.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, GLframebuffer *buffer, GLuint bit );
+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/OPENGL32.DEF b/src/mesa/drivers/d3d/OPENGL32.DEF
new file mode 100644
index 00000000000..b32bd1fef81
--- /dev/null
+++ b/src/mesa/drivers/d3d/OPENGL32.DEF
@@ -0,0 +1,442 @@
+;===========================================================================
+;
+; 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
+
+
+
diff --git a/src/mesa/drivers/d3d/WGL.C b/src/mesa/drivers/d3d/WGL.C
new file mode 100644
index 00000000000..e3b95e1de72
--- /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 = _mesa_create_visual( TRUE,
+ FALSE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8,8, /* r, g, b, a bits */
+ 0, /* index bits */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8,8,8,8, /* accum_bits */
+ 1 );
+
+ if ( pD3DDefault->gl_visual == NULL)
+ {
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa context */
+ pD3DDefault->gl_ctx = _mesa_create_context( pD3DDefault->gl_visual, NULL, pD3DDefault, GL_TRUE );
+ if ( pD3DDefault->gl_ctx == NULL )
+ {
+ _mesa_destroy_visual( pD3DDefault->gl_visual );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pD3DDefault->gl_buffer = _mesa_create_framebuffer( pD3DDefault->gl_visual );
+ if ( pD3DDefault->gl_buffer == NULL )
+ {
+ _mesa_destroy_visual( pD3DDefault->gl_visual );
+ _mesa_destroy_context( pD3DDefault->gl_ctx );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+ SetupDDPointers( pD3DDefault->gl_ctx );
+ _mesa_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 = _mesa_create_visual( TRUE,
+ TRUE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 8,8,8,8, /* r, g, b, a bits */
+ 0, /* index bits */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 16,16,16,16,/* accum_bits */
+ 1 );
+ if ( pNewContext->gl_visual == NULL)
+ {
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa context */
+ pNewContext->gl_ctx = _mesa_create_context( pNewContext->gl_visual, NULL, pNewContext, GL_TRUE );
+ if ( pNewContext->gl_ctx == NULL )
+ {
+ _mesa_destroy_visual( pNewContext->gl_visual );
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pNewContext->gl_buffer = _mesa_create_framebuffer( pNewContext->gl_visual );
+ if ( pNewContext->gl_buffer == NULL )
+ {
+ _mesa_destroy_visual( pNewContext->gl_visual );
+ _mesa_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 );
+ _mesa_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 );
+ _mesa_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 )
+ {
+ _mesa_destroy_visual( pContext->gl_visual );
+ pContext->gl_visual = NULL;
+ }
+ if ( pContext->gl_buffer )
+ {
+ _mesa_destroy_framebuffer( pContext->gl_buffer );
+ pContext->gl_buffer = NULL;
+ }
+ if ( pContext->gl_ctx )
+ {
+ _mesa_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 00000000000..9ff0650518b
--- /dev/null
+++ b/src/mesa/drivers/d3d/d3dText.h
@@ -0,0 +1,53 @@
+#ifndef D3D_TEXT_H
+#define D3D_TEXT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+#define D3DLTEXT_BITSUSED 0xFFFFFFFF
+#define MAX_VERTICES 700 // (14*40) 14 per character, 40 characters
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _d3dText_metrics
+{
+ float fntYScale,
+ fntXScale;
+
+ int fntXSpacing,
+ fntYSpacing;
+
+ DWORD dwColor;
+ LPDIRECT3DDEVICE3 lpD3DDevice;
+
+} D3DFONTMETRICS, *PD3DFONTMETRICS;
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+extern BOOL InitD3DText( void );
+extern void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics );
+extern void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/mesa/drivers/directfb/idirectfbgl_mesa.c b/src/mesa/drivers/directfb/idirectfbgl_mesa.c
index e8ed192be3e..1c481af3f2a 100644
--- a/src/mesa/drivers/directfb/idirectfbgl_mesa.c
+++ b/src/mesa/drivers/directfb/idirectfbgl_mesa.c
@@ -310,6 +310,13 @@ set_viewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
_mesa_ResizeBuffersMESA();
}
+/* required but not used */
+static void
+set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
+{
+ return;
+}
+
static void
delete_renderbuffer( struct gl_renderbuffer *render )
{
@@ -555,6 +562,7 @@ dfb_mesa_create_context( GLcontext *context,
_swsetup_Wakeup( context );
swdd = _swrast_GetDeviceDriverReference( context );
+ swdd->SetBuffer = set_buffer;
_mesa_init_renderbuffer( &data->render, 0 );
data->render.InternalFormat = GL_RGBA;
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 9e1b36252ff..4a7a6552ac0 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -14,8 +14,7 @@ COMMON_SOURCES = \
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=
WINLIB=
-INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES) \
- `pkg-config --cflags libdrm`
+INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
OBJECTS = $(C_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
@@ -25,8 +24,6 @@ WINOBJ=
WINLIB=-L$(MESA)/src/glx/mini
MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
INCLUDES = $(MINIGLX_INCLUDES) \
- -I$(DRM_SOURCE_PATH)/shared-core \
- -I$(DRM_SOURCE_PATH)/libdrm \
$(SHARED_INCLUDES)
OBJECTS = $(C_SOURCES:.c=.o) \
@@ -40,7 +37,6 @@ SHARED_INCLUDES = \
-I. \
-I$(TOP)/src/mesa/drivers/dri/common \
-Iserver \
- -I$(DRM_SOURCE_PATH)/shared-core \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/mesa \
@@ -52,15 +48,16 @@ SHARED_INCLUDES = \
-I$(TOP)/src/mesa/swrast \
-I$(TOP)/src/mesa/swrast_setup \
-I$(TOP)/src/egl/main \
- -I$(TOP)/src/egl/drivers/dri
+ -I$(TOP)/src/egl/drivers/dri \
+ `pkg-config --cflags libdrm`
##### RULES #####
.c.o:
- $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
.S.o:
- $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
##### TARGETS #####
@@ -85,11 +82,10 @@ $(LIB_DIR)/$(LIBNAME): $(LIBNAME)
# Run 'make depend' to update the dependencies if you change
# what's included by any source file.
-.PHONY: depend
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
touch depend
- $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(C_SOURCES) $(ASM_SOURCES) \
- >& /dev/null
+ $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
+ $(ASM_SOURCES) > /dev/null
# Emacs tags
diff --git a/src/mesa/drivers/dri/common/glcontextmodes.c b/src/mesa/drivers/dri/common/glcontextmodes.c
index d1297991497..edb04463f61 100644
--- a/src/mesa/drivers/dri/common/glcontextmodes.c
+++ b/src/mesa/drivers/dri/common/glcontextmodes.c
@@ -104,7 +104,7 @@ _gl_convert_to_x_visual_type( int visualType )
GrayScale, StaticGray
};
- return ( (unsigned) (visualType - GLX_TRUE_COLOR) <= NUM_VISUAL_TYPES )
+ return ( (unsigned) (visualType - GLX_TRUE_COLOR) < NUM_VISUAL_TYPES )
? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
}
@@ -182,6 +182,15 @@ _gl_copy_visual_to_context_mode( __GLcontextModes * mode,
mode->transparentIndex = config->transparentIndex;
mode->swapMethod = GLX_SWAP_UNDEFINED_OML;
+
+ mode->bindToTextureRgb = (mode->rgbMode) ? GL_TRUE : GL_FALSE;
+ mode->bindToTextureRgba = (mode->rgbMode && mode->alphaBits) ?
+ GL_TRUE : GL_FALSE;
+ mode->bindToMipmapTexture = mode->rgbMode ? GL_TRUE : GL_FALSE;
+ mode->bindToTextureTargets = mode->rgbMode ?
+ GLX_TEXTURE_1D_BIT_EXT | GLX_TEXTURE_2D_BIT_EXT |
+ GLX_TEXTURE_RECTANGLE_BIT_EXT : 0;
+ mode->yInverted = GL_FALSE;
}
@@ -313,6 +322,21 @@ _gl_get_context_mode_data(const __GLcontextModes *mode, int attribute,
case GLX_SAMPLES_SGIS:
*value_return = mode->samples;
return 0;
+ case GLX_BIND_TO_TEXTURE_RGB_EXT:
+ *value_return = mode->bindToTextureRgb;
+ return 0;
+ case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+ *value_return = mode->bindToTextureRgba;
+ return 0;
+ case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+ *value_return = mode->bindToMipmapTexture;
+ return 0;
+ case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+ *value_return = mode->bindToTextureTargets;
+ return 0;
+ case GLX_Y_INVERTED_EXT:
+ *value_return = mode->yInverted;
+ return 0;
/* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX.
* It is ONLY for communication between the GLX client and the GLX
@@ -383,6 +407,11 @@ _gl_context_modes_create( unsigned count, size_t minimum_size )
(*next)->xRenderable = GLX_DONT_CARE;
(*next)->fbconfigID = GLX_DONT_CARE;
(*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+ (*next)->bindToTextureRgb = GLX_DONT_CARE;
+ (*next)->bindToTextureRgba = GLX_DONT_CARE;
+ (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+ (*next)->bindToTextureTargets = 0;
+ (*next)->yInverted = GLX_DONT_CARE;
next = & ((*next)->next);
}
@@ -495,5 +524,10 @@ _gl_context_modes_are_same( const __GLcontextModes * a,
(a->maxPbufferPixels == b->maxPbufferPixels) &&
(a->optimalPbufferWidth == b->optimalPbufferWidth) &&
(a->optimalPbufferHeight == b->optimalPbufferHeight) &&
- (a->swapMethod == b->swapMethod) );
+ (a->swapMethod == b->swapMethod) &&
+ (a->bindToTextureRgb == b->bindToTextureRgb) &&
+ (a->bindToTextureRgba == b->bindToTextureRgba) &&
+ (a->bindToMipmapTexture == b->bindToMipmapTexture) &&
+ (a->bindToTextureTargets == b->bindToTextureTargets) &&
+ (a->yInverted == b->yInverted) );
}
diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c
index 41316de1fc4..b0e8c4c1c28 100644
--- a/src/mesa/drivers/dri/common/texmem.c
+++ b/src/mesa/drivers/dri/common/texmem.c
@@ -410,6 +410,7 @@ static void driTexturesGone( driTexHeap * heap, int offset, int size,
fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId,
(int)size, (int)offset );
mmDumpMemInfo( heap->memory_heap );
+ FREE(t);
return;
}
t->heap = heap;
diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c
index fbe1991fa5d..e3eca86da1b 100644
--- a/src/mesa/drivers/dri/common/utils.c
+++ b/src/mesa/drivers/dri/common/utils.c
@@ -361,25 +361,26 @@ driCheckDriDdxDrmVersions3(const char * driver_name,
const __DRIversion * drmExpected)
{
static const char format[] = "%s DRI driver expected %s version %d.%d.x "
- "but got version %d.%d.%d";
+ "but got version %d.%d.%d\n";
static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x "
- "but got version %d.%d.%d";
+ "but got version %d.%d.%d\n";
/* Check the DRI version */
if ( (driActual->major != driExpected->major)
|| (driActual->minor < driExpected->minor) ) {
- __driUtilMessage(format, driver_name, "DRI",
+ fprintf(stderr, format, driver_name, "DRI",
driExpected->major, driExpected->minor,
driActual->major, driActual->minor, driActual->patch);
return GL_FALSE;
}
/* Check that the DDX driver version is compatible */
- if ( (ddxActual->major < ddxExpected->major_min)
+ /* for miniglx we pass in -1 so we can ignore the DDX version */
+ if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min)
|| (ddxActual->major > ddxExpected->major_max)
- || (ddxActual->minor < ddxExpected->minor) ) {
- __driUtilMessage(format2, driver_name, "DDX",
+ || (ddxActual->minor < ddxExpected->minor)) ) {
+ fprintf(stderr, format2, driver_name, "DDX",
ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor,
ddxActual->major, ddxActual->minor, ddxActual->patch);
return GL_FALSE;
@@ -388,7 +389,7 @@ driCheckDriDdxDrmVersions3(const char * driver_name,
/* Check that the DRM driver version is compatible */
if ( (drmActual->major != drmExpected->major)
|| (drmActual->minor < drmExpected->minor) ) {
- __driUtilMessage(format, driver_name, "DRM",
+ fprintf(stderr, format, driver_name, "DRM",
drmExpected->major, drmExpected->minor,
drmActual->major, drmActual->minor, drmActual->patch);
return GL_FALSE;
diff --git a/src/mesa/drivers/dri/common/xmlpool/Makefile b/src/mesa/drivers/dri/common/xmlpool/Makefile
new file mode 100644
index 00000000000..ef94541c374
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlpool/Makefile
@@ -0,0 +1,96 @@
+# Convenient makefile for managing translations.
+
+# Prerequisites:
+# - GNU gettext
+# - Python
+
+# Adding new translations
+# -----------------------
+
+# To start working on a new translation edit the POS=... line
+# below. If you want to add for example a french translation, add
+# fr.po.
+
+# Then run "make po" to generate a fresh .po file from translatable
+# strings in t_options.h. Now you can edit the new .po file (fr.po in
+# the example above) to translate the strings. Please make sure that
+# your editor encodes the file in UTF-8.
+
+# Updating existing translations
+# ------------------------------
+
+# Run "make po" to update .po files with new translatable strings from
+# t_options.h. Now you can edit the .po files you're interested
+# in. Please make sure that your editor encodes the file in UTF-8.
+
+# Updating options.h
+# ------------------
+
+# Finally run "make" to generate options.h from t_options.h with all
+# translations. Now you can rebuild the drivers. Any common options
+# used by the drivers will have option descriptions with the latest
+# translations.
+
+# Publishing translations
+# -----------------------
+
+# To get your translation(s) into Mesa CVS, please send me your
+# <lang>.po file.
+
+# More information:
+# - info gettext
+
+# The set of supported languages. Add languages as needed.
+POS=de.po es.po nl.po fr.po
+
+#
+# Don't change anything below, unless you know what you're doing.
+#
+LANGS=$(POS:%.po=%)
+MOS=$(POS:%.po=%/LC_MESSAGES/options.mo)
+POT=xmlpool.pot
+
+.PHONY: all clean pot po mo
+
+all: options.h
+
+# Only intermediate files are cleaned up. options.h is not deleted because
+# it's in CVS.
+clean:
+ rm -f $(POT) *~
+ rm -rf $(LANGS)
+
+# Default target options.h
+options.h: t_options.h mo
+ python gen_xmlpool.py $(LANGS) > options.h
+
+# Update .mo files from the corresponding .po files.
+mo:
+ @for mo in $(MOS); do \
+ lang=$${mo%%/*}; \
+ echo "Updating $$mo from $$lang.po."; \
+ mkdir -p $${mo%/*}; \
+ msgfmt -o $$mo $$lang.po; \
+ done
+
+# Use this target to create or update .po files with new messages in
+# driconf.py.
+po: $(POS)
+
+pot: $(POT)
+
+# Extract message catalog from driconf.py.
+$(POT): t_options.h
+ xgettext -L C --from-code utf-8 -o $(POT) t_options.h
+
+# Create or update a .po file for a specific language.
+%.po: $(POT)
+ @if [ -f $@ ]; then \
+ echo "Merging new strings from $(POT) into $@."; \
+ mv $@ $@~; \
+ msgmerge -o $@ $@~ $(POT); \
+ else \
+ echo "Initializing $@ from $(POT)."; \
+ msginit -i $(POT) -o $@~ --locale=$*; \
+ sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $@~ > $@; \
+ fi
diff --git a/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py b/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py
new file mode 100644
index 00000000000..7398c4cd0b2
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlpool/gen_xmlpool.py
@@ -0,0 +1,191 @@
+#!/usr/bin/python
+
+import sys
+import gettext
+import re
+
+# List of supported languages
+languages = sys.argv[1:]
+
+# Escape special characters in C strings
+def escapeCString (s):
+ escapeSeqs = {'\a' : '\\a', '\b' : '\\b', '\f' : '\\f', '\n' : '\\n',
+ '\r' : '\\r', '\t' : '\\t', '\v' : '\\v', '\\' : '\\\\'}
+ # " -> '' is a hack. Quotes (") aren't possible in XML attributes.
+ # Better use Unicode characters for typographic quotes in option
+ # descriptions and translations.
+ i = 0
+ r = ''
+ while i < len(s):
+ # Special case: escape double quote with \u201c or \u201d, depending
+ # on whether it's an open or close quote. This is needed because plain
+ # double quotes are not possible in XML attributes.
+ if s[i] == '"':
+ if i == len(s)-1 or s[i+1].isspace():
+ # close quote
+ q = u'\u201c'
+ else:
+ # open quote
+ q = u'\u201d'
+ r = r + q
+ elif escapeSeqs.has_key(s[i]):
+ r = r + escapeSeqs[s[i]]
+ else:
+ r = r + s[i]
+ i = i + 1
+ return r
+
+# Expand escape sequences in C strings (needed for gettext lookup)
+def expandCString (s):
+ escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n',
+ 'r' : '\r', 't' : '\t', 'v' : '\v',
+ '"' : '"', '\\' : '\\'}
+ i = 0
+ escape = False
+ hexa = False
+ octa = False
+ num = 0
+ digits = 0
+ r = ''
+ while i < len(s):
+ if not escape:
+ if s[i] == '\\':
+ escape = True
+ else:
+ r = r + s[i]
+ elif hexa:
+ if (s[i] >= '0' and s[i] <= '9') or \
+ (s[i] >= 'a' and s[i] <= 'f') or \
+ (s[i] >= 'A' and s[i] <= 'F'):
+ num = num * 16 + int(s[i],16)
+ digits = digits + 1
+ else:
+ digits = 2
+ if digits >= 2:
+ hexa = False
+ escape = False
+ r = r + chr(num)
+ elif octa:
+ if s[i] >= '0' and s[i] <= '7':
+ num = num * 8 + int(s[i],8)
+ digits = digits + 1
+ else:
+ digits = 3
+ if digits >= 3:
+ octa = False
+ escape = False
+ r = r + chr(num)
+ else:
+ if escapeSeqs.has_key(s[i]):
+ r = r + escapeSeqs[s[i]]
+ escape = False
+ elif s[i] >= '0' and s[i] <= '7':
+ octa = True
+ num = int(s[i],8)
+ if num <= 3:
+ digits = 1
+ else:
+ digits = 2
+ elif s[i] == 'x' or s[i] == 'X':
+ hexa = True
+ num = 0
+ digits = 0
+ else:
+ r = r + s[i]
+ escape = False
+ i = i + 1
+ return r
+
+# Expand matches. The first match is always a DESC or DESC_BEGIN match.
+# Subsequent matches are ENUM matches.
+#
+# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7
+# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5
+def expandMatches (matches, translations, end=None):
+ assert len(matches) > 0
+ nTranslations = len(translations)
+ i = 0
+ # Expand the description+enums for all translations
+ for lang,trans in translations:
+ i = i + 1
+ # Make sure that all but the last line of a simple description
+ # are extended with a backslash.
+ suffix = ''
+ if len(matches) == 1 and i < len(translations) and \
+ not matches[0].expand (r'\7').endswith('\\'):
+ suffix = ' \\'
+ # Expand the description line. Need to use ugettext in order to allow
+ # non-ascii unicode chars in the original English descriptions.
+ text = escapeCString (trans.ugettext (unicode (expandCString (
+ matches[0].expand (r'\5')), "utf-8"))).encode("utf-8")
+ print matches[0].expand (r'\1' + lang + r'\3"' + text + r'"\7') + suffix
+ # Expand any subsequent enum lines
+ for match in matches[1:]:
+ text = escapeCString (trans.ugettext (unicode (expandCString (
+ match.expand (r'\3')), "utf-8"))).encode("utf-8")
+ print match.expand (r'\1"' + text + r'"\5')
+
+ # Expand description end
+ if end:
+ print end,
+
+# Compile a list of translation classes to all supported languages.
+# The first translation is always a NullTranslations.
+translations = [("en", gettext.NullTranslations())]
+for lang in languages:
+ try:
+ trans = gettext.translation ("options", ".", [lang])
+ except IOError:
+ sys.stderr.write ("Warning: language '%s' not found.\n" % lang)
+ continue
+ translations.append ((lang, trans))
+
+# Regular expressions:
+reLibintl_h = re.compile (r'#\s*include\s*<libintl.h>')
+reDESC = re.compile (r'(\s*DRI_CONF_DESC\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reDESC_BEGIN = re.compile (r'(\s*DRI_CONF_DESC_BEGIN\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reENUM = re.compile (r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$')
+reDESC_END = re.compile (r'\s*DRI_CONF_DESC_END')
+
+# Print a header
+print \
+"/***********************************************************************\n" \
+" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \
+" ***********************************************************************/"
+
+# Process the options template and generate options.h with all
+# translations.
+template = file ("t_options.h", "r")
+descMatches = []
+for line in template:
+ if len(descMatches) > 0:
+ matchENUM = reENUM .match (line)
+ matchDESC_END = reDESC_END.match (line)
+ if matchENUM:
+ descMatches.append (matchENUM)
+ elif matchDESC_END:
+ expandMatches (descMatches, translations, line)
+ descMatches = []
+ else:
+ sys.stderr.write (
+ "Warning: unexpected line inside description dropped:\n%s\n" \
+ % line)
+ continue
+ if reLibintl_h.search (line):
+ # Ignore (comment out) #include <libintl.h>
+ print "/* %s * commented out by gen_xmlpool.py */" % line
+ continue
+ matchDESC = reDESC .match (line)
+ matchDESC_BEGIN = reDESC_BEGIN.match (line)
+ if matchDESC:
+ assert len(descMatches) == 0
+ expandMatches ([matchDESC], translations)
+ elif matchDESC_BEGIN:
+ assert len(descMatches) == 0
+ descMatches = [matchDESC_BEGIN]
+ else:
+ print line,
+
+if len(descMatches) > 0:
+ sys.stderr.write ("Warning: unterminated description at end of file.\n")
+ expandMatches (descMatches, translations)
diff --git a/src/mesa/drivers/dri/dri_client/Makefile b/src/mesa/drivers/dri/dri_client/Makefile
new file mode 100644
index 00000000000..9ab60cdaf80
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/Makefile
@@ -0,0 +1,60 @@
+# src/mesa/drivers/dri/gamma/Makefile
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+# Get rid of this:
+#
+DEFINES += -DGLX_DIRECT_RENDERING
+
+C_SOURCES = \
+ xf86drm.c \
+ xf86drmHash.c \
+ xf86drmRandom.c \
+ xf86drmSL.c \
+
+
+
+OBJECTS = $(C_SOURCES:.c=.o)
+
+INCLUDES = \
+ -I$(TOP)/include \
+ -I$(DRM_SOURCE_PATH)/shared-core \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa/glapi \
+ -Iimports
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+
+##### TARGETS #####
+
+default: depend dri.a
+
+
+# Run 'make dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(C_SOURCES) $(ASM_SOURCES)
+ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDES) \
+ $(C_SOURCES) $(ASM_SOURCES)
+
+
+dri.a: $(OBJECTS)
+ rm -f $@
+ ar rcv $@ $(OBJECTS)
+ ranlib $@
+
+# Remove .o and backup files
+clean:
+ -rm -f *.o */*.o *~ *.so *.a depend depend.bak
+
+install:
+
+include depend
diff --git a/src/mesa/drivers/dri/dri_client/imports/xf86drm.h b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h
new file mode 100644
index 00000000000..d3d78eb84e8
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/imports/xf86drm.h
@@ -0,0 +1,636 @@
+/**
+ * \file xf86drm.h
+ * OS-independent header for DRM user-level library interface.
+ *
+ * \author Rickard E. (Rik) Faith <[email protected]>
+ */
+
+/*
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.26 2003/08/16 19:26:37 dawes Exp $ */
+
+#ifndef _XF86DRM_H_
+#define _XF86DRM_H_
+
+#include <drm.h>
+
+ /* Defaults, if nothing set in xf86config */
+#define DRM_DEV_UID 0
+#define DRM_DEV_GID 0
+/* Default /dev/dri directory permissions 0755 */
+#define DRM_DEV_DIRMODE \
+ (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+
+#define DRM_DIR_NAME "/dev/dri"
+#define DRM_DEV_NAME "%s/card%d"
+#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
+
+#define DRM_ERR_NO_DEVICE (-1001)
+#define DRM_ERR_NO_ACCESS (-1002)
+#define DRM_ERR_NOT_ROOT (-1003)
+#define DRM_ERR_INVALID (-1004)
+#define DRM_ERR_NO_FD (-1005)
+
+#define DRM_AGP_NO_HANDLE 0
+
+typedef unsigned int drmSize, *drmSizePtr; /**< For mapped regions */
+typedef void *drmAddress, **drmAddressPtr; /**< For mapped regions */
+
+/**
+ * Driver version information.
+ *
+ * \sa drmGetVersion() and drmSetVersion().
+ */
+typedef struct _drmVersion {
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel; /**< Patch level */
+ int name_len; /**< Length of name buffer */
+ char *name; /**< Name of driver */
+ int date_len; /**< Length of date buffer */
+ char *date; /**< User-space buffer to hold date */
+ int desc_len; /**< Length of desc buffer */
+ char *desc; /**< User-space buffer to hold desc */
+} drmVersion, *drmVersionPtr;
+
+typedef struct _drmStats {
+ unsigned long count; /**< Number of data */
+ struct {
+ unsigned long value; /**< Value from kernel */
+ const char *long_format; /**< Suggested format for long_name */
+ const char *long_name; /**< Long name for value */
+ const char *rate_format; /**< Suggested format for rate_name */
+ const char *rate_name; /**< Short name for value per second */
+ int isvalue; /**< True if value (vs. counter) */
+ const char *mult_names; /**< Multiplier names (e.g., "KGM") */
+ int mult; /**< Multiplier value (e.g., 1024) */
+ int verbose; /**< Suggest only in verbose output */
+ } data[15];
+} drmStatsT;
+
+
+ /* All of these enums *MUST* match with the
+ kernel implementation -- so do *NOT*
+ change them! (The drmlib implementation
+ will just copy the flags instead of
+ translating them.) */
+typedef enum {
+ DRM_FRAME_BUFFER = 0, /**< WC, no caching, no core dump */
+ DRM_REGISTERS = 1, /**< no caching, no core dump */
+ DRM_SHM = 2, /**< shared, cached */
+ DRM_AGP = 3, /**< AGP/GART */
+ DRM_SCATTER_GATHER = 4 /**< PCI scatter/gather */
+} drmMapType;
+
+typedef enum {
+ DRM_RESTRICTED = 0x0001, /**< Cannot be mapped to client-virtual */
+ DRM_READ_ONLY = 0x0002, /**< Read-only in client-virtual */
+ DRM_LOCKED = 0x0004, /**< Physical pages locked */
+ DRM_KERNEL = 0x0008, /**< Kernel requires access */
+ DRM_WRITE_COMBINING = 0x0010, /**< Use write-combining, if available */
+ DRM_CONTAINS_LOCK = 0x0020, /**< SHM page that contains lock */
+ DRM_REMOVABLE = 0x0040 /**< Removable mapping */
+} drmMapFlags;
+
+/**
+ * \warning These values *MUST* match drm.h
+ */
+typedef enum {
+ /** \name Flags for DMA buffer dispatch */
+ /*@{*/
+ DRM_DMA_BLOCK = 0x01, /**<
+ * Block until buffer dispatched.
+ *
+ * \note the buffer may not yet have been
+ * processed by the hardware -- getting a
+ * hardware lock with the hardware quiescent
+ * will ensure that the buffer has been
+ * processed.
+ */
+ DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+ DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
+ /*@}*/
+
+ /** \name Flags for DMA buffer request */
+ /*@{*/
+ DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
+ DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
+ DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
+ /*@}*/
+} drmDMAFlags;
+
+typedef enum {
+ DRM_PAGE_ALIGN = 0x01,
+ DRM_AGP_BUFFER = 0x02,
+ DRM_SG_BUFFER = 0x04
+} drmBufDescFlags;
+
+typedef enum {
+ DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
+ DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
+ DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
+ DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
+ /* These *HALT* flags aren't supported yet
+ -- they will be used to support the
+ full-screen DGA-like mode. */
+ DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+ DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
+} drmLockFlags;
+
+typedef enum {
+ DRM_CONTEXT_PRESERVED = 0x01, /**< This context is preserved and
+ never swapped. */
+ DRM_CONTEXT_2DONLY = 0x02 /**< This context is for 2D rendering only. */
+} drm_context_tFlags, *drm_context_tFlagsPtr;
+
+typedef struct _drmBufDesc {
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+} drmBufDesc, *drmBufDescPtr;
+
+typedef struct _drmBufInfo {
+ int count; /**< Number of buffers described in list */
+ drmBufDescPtr list; /**< List of buffer descriptions */
+} drmBufInfo, *drmBufInfoPtr;
+
+typedef struct _drmBuf {
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ drmAddress address; /**< Address */
+} drmBuf, *drmBufPtr;
+
+/**
+ * Buffer mapping information.
+ *
+ * Used by drmMapBufs() and drmUnmapBufs() to store information about the
+ * mapped buffers.
+ */
+typedef struct _drmBufMap {
+ int count; /**< Number of buffers mapped */
+ drmBufPtr list; /**< Buffers */
+} drmBufMap, *drmBufMapPtr;
+
+typedef struct _drmLock {
+ volatile unsigned int lock;
+ char padding[60];
+ /* This is big enough for most current (and future?) architectures:
+ DEC Alpha: 32 bytes
+ Intel Merced: ?
+ Intel P5/PPro/PII/PIII: 32 bytes
+ Intel StrongARM: 32 bytes
+ Intel i386/i486: 16 bytes
+ MIPS: 32 bytes (?)
+ Motorola 68k: 16 bytes
+ Motorola PowerPC: 32 bytes
+ Sun SPARC: 32 bytes
+ */
+} drmLock, *drmLockPtr;
+
+/**
+ * Indices here refer to the offset into
+ * list in drmBufInfo
+ */
+typedef struct _drmDMAReq {
+ drm_context_t context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ int *send_list; /**< List of handles to buffers */
+ int *send_sizes; /**< Lengths of data to send, in bytes */
+ drmDMAFlags flags; /**< Flags */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size of buffers requested */
+ int *request_list; /**< Buffer information */
+ int *request_sizes; /**< Minimum acceptable sizes */
+ int granted_count; /**< Number of buffers granted at this size */
+} drmDMAReq, *drmDMAReqPtr;
+
+typedef struct _drmRegion {
+ drm_handle_t handle;
+ unsigned int offset;
+ drmSize size;
+ drmAddress map;
+} drmRegion, *drmRegionPtr;
+
+typedef struct _drmTextureRegion {
+ unsigned char next;
+ unsigned char prev;
+ unsigned char in_use;
+ unsigned char padding; /**< Explicitly pad this out */
+ unsigned int age;
+} drmTextureRegion, *drmTextureRegionPtr;
+
+
+typedef enum {
+ DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
+ DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
+ DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
+} drmVBlankSeqType;
+
+typedef struct _drmVBlankReq {
+ drmVBlankSeqType type;
+ unsigned int sequence;
+ unsigned long signal;
+} drmVBlankReq, *drmVBlankReqPtr;
+
+typedef struct _drmVBlankReply {
+ drmVBlankSeqType type;
+ unsigned int sequence;
+ long tval_sec;
+ long tval_usec;
+} drmVBlankReply, *drmVBlankReplyPtr;
+
+typedef union _drmVBlank {
+ drmVBlankReq request;
+ drmVBlankReply reply;
+} drmVBlank, *drmVBlankPtr;
+
+typedef struct _drmSetVersion {
+ int drm_di_major;
+ int drm_di_minor;
+ int drm_dd_major;
+ int drm_dd_minor;
+} drmSetVersion, *drmSetVersionPtr;
+
+
+#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
+
+#define DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# if defined(__i386) || defined(__amd64__)
+ /* Reflect changes here to drmP.h */
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ int __dummy; /* Can't mark eax as clobbered */ \
+ __asm__ __volatile__( \
+ "lock ; cmpxchg %4,%1\n\t" \
+ "setnz %0" \
+ : "=d" (__ret), \
+ "=m" (__drm_dummy_lock(lock)), \
+ "=a" (__dummy) \
+ : "2" (old), \
+ "r" (new)); \
+ } while (0)
+
+#elif defined(__alpha__)
+
+#define DRM_CAS(lock, old, new, ret) \
+ do { \
+ int old32; \
+ int cur32; \
+ __asm__ __volatile__( \
+ " mb\n" \
+ " zap %4, 0xF0, %0\n" \
+ " ldl_l %1, %2\n" \
+ " zap %1, 0xF0, %1\n" \
+ " cmpeq %0, %1, %1\n" \
+ " beq %1, 1f\n" \
+ " bis %5, %5, %1\n" \
+ " stl_c %1, %2\n" \
+ "1: xor %1, 1, %1\n" \
+ " stl %1, %3" \
+ : "+r" (old32), \
+ "+&r" (cur32), \
+ "=m" (__drm_dummy_lock(lock)),\
+ "=m" (ret) \
+ : "r" (old), \
+ "r" (new)); \
+ } while(0)
+
+#elif defined(__sparc__)
+
+#define DRM_CAS(lock,old,new,__ret) \
+do { register unsigned int __old __asm("o0"); \
+ register unsigned int __new __asm("o1"); \
+ register volatile unsigned int *__lock __asm("o2"); \
+ __old = old; \
+ __new = new; \
+ __lock = (volatile unsigned int *)lock; \
+ __asm__ __volatile__( \
+ /*"cas [%2], %3, %0"*/ \
+ ".word 0xd3e29008\n\t" \
+ /*"membar #StoreStore | #StoreLoad"*/ \
+ ".word 0x8143e00a" \
+ : "=&r" (__new) \
+ : "0" (__new), \
+ "r" (__lock), \
+ "r" (__old) \
+ : "memory"); \
+ __ret = (__new != __old); \
+} while(0)
+
+#elif defined(__ia64__)
+
+#ifdef __INTEL_COMPILER
+/* this currently generates bad code (missing stop bits)... */
+#include <ia64intrin.h>
+
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ unsigned long __result, __old = (old) & 0xffffffff; \
+ __mf(); \
+ __result = _InterlockedCompareExchange_acq(&__drm_dummy_lock(lock), (new), __old);\
+ __ret = (__result) != (__old); \
+/* __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
+ (old), (new)) \
+ != (old)); */\
+ } while (0)
+
+#else
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ unsigned int __result, __old = (old); \
+ __asm__ __volatile__( \
+ "mf\n" \
+ "mov ar.ccv=%2\n" \
+ ";;\n" \
+ "cmpxchg4.acq %0=%1,%3,ar.ccv" \
+ : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \
+ : "r" ((unsigned long)__old), "r" (new) \
+ : "memory"); \
+ __ret = (__result) != (__old); \
+ } while (0)
+
+#endif
+
+#elif defined(__powerpc__)
+
+#define DRM_CAS(lock,old,new,__ret) \
+ do { \
+ __asm__ __volatile__( \
+ "sync;" \
+ "0: lwarx %0,0,%1;" \
+ " xor. %0,%3,%0;" \
+ " bne 1f;" \
+ " stwcx. %2,0,%1;" \
+ " bne- 0b;" \
+ "1: " \
+ "sync;" \
+ : "=&r"(__ret) \
+ : "r"(lock), "r"(new), "r"(old) \
+ : "cr0", "memory"); \
+ } while (0)
+
+#endif /* architecture */
+#endif /* __GNUC__ >= 2 */
+
+#ifndef DRM_CAS
+#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
+#endif
+
+#if defined(__alpha__) || defined(__powerpc__)
+#define DRM_CAS_RESULT(_result) int _result
+#else
+#define DRM_CAS_RESULT(_result) char _result
+#endif
+
+#define DRM_LIGHT_LOCK(fd,lock,context) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
+ if (__ret) drmGetLock(fd,context,0); \
+ } while(0)
+
+ /* This one counts fast locks -- for
+ benchmarking only. */
+#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
+ if (__ret) drmGetLock(fd,context,0); \
+ else ++count; \
+ } while(0)
+
+#define DRM_LOCK(fd,lock,context,flags) \
+ do { \
+ if (flags) drmGetLock(fd,context,flags); \
+ else DRM_LIGHT_LOCK(fd,lock,context); \
+ } while(0)
+
+#define DRM_UNLOCK(fd,lock,context) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \
+ if (__ret) drmUnlock(fd,context); \
+ } while(0)
+
+ /* Simple spin locks */
+#define DRM_SPINLOCK(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ do { \
+ DRM_CAS(spin,0,val,__ret); \
+ if (__ret) while ((spin)->lock); \
+ } while (__ret); \
+ } while(0)
+
+#define DRM_SPINLOCK_TAKE(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ int cur; \
+ do { \
+ cur = (*spin).lock; \
+ DRM_CAS(spin,cur,val,__ret); \
+ } while (__ret); \
+ } while(0)
+
+#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \
+ do { \
+ int __i; \
+ __ret = 1; \
+ for (__i = 0; __ret && __i < count; __i++) { \
+ DRM_CAS(spin,0,val,__ret); \
+ if (__ret) for (;__i < count && (spin)->lock; __i++); \
+ } \
+ } while(0)
+
+#define DRM_SPINUNLOCK(spin,val) \
+ do { \
+ DRM_CAS_RESULT(__ret); \
+ if ((*spin).lock == val) { /* else server stole lock */ \
+ do { \
+ DRM_CAS(spin,val,0,__ret); \
+ } while (__ret); \
+ } \
+ } while(0)
+
+/* General user-level programmer's API: unprivileged */
+extern int drmAvailable(void);
+extern int drmOpen(const char *name, const char *busid);
+extern int drmClose(int fd);
+extern drmVersionPtr drmGetVersion(int fd);
+extern drmVersionPtr drmGetLibVersion(int fd);
+extern void drmFreeVersion(drmVersionPtr);
+extern int drmGetMagic(int fd, drm_magic_t * magic);
+extern char *drmGetBusid(int fd);
+extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
+ int funcnum);
+extern int drmGetMap(int fd, int idx, drm_handle_t *offset,
+ drmSize *size, drmMapType *type,
+ drmMapFlags *flags, drm_handle_t *handle,
+ int *mtrr);
+extern int drmGetClient(int fd, int idx, int *auth, int *pid,
+ int *uid, unsigned long *magic,
+ unsigned long *iocs);
+extern int drmGetStats(int fd, drmStatsT *stats);
+extern int drmSetInterfaceVersion(int fd, drmSetVersion *version);
+extern int drmCommandNone(int fd, unsigned long drmCommandIndex);
+extern int drmCommandRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+extern int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size);
+
+/* General user-level programmer's API: X server (root) only */
+extern void drmFreeBusid(const char *busid);
+extern int drmSetBusid(int fd, const char *busid);
+extern int drmAuthMagic(int fd, drm_magic_t magic);
+extern int drmAddMap(int fd,
+ drm_handle_t offset,
+ drmSize size,
+ drmMapType type,
+ drmMapFlags flags,
+ drm_handle_t * handle);
+extern int drmRmMap(int fd, drm_handle_t handle);
+extern int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id,
+ drm_handle_t handle);
+
+extern int drmAddBufs(int fd, int count, int size,
+ drmBufDescFlags flags,
+ int agp_offset);
+extern int drmMarkBufs(int fd, double low, double high);
+extern int drmCreateContext(int fd, drm_context_t * handle);
+extern int drmSetContextFlags(int fd, drm_context_t context,
+ drm_context_tFlags flags);
+extern int drmGetContextFlags(int fd, drm_context_t context,
+ drm_context_tFlagsPtr flags);
+extern int drmAddContextTag(int fd, drm_context_t context, void *tag);
+extern int drmDelContextTag(int fd, drm_context_t context);
+extern void *drmGetContextTag(int fd, drm_context_t context);
+extern drm_context_t * drmGetReservedContextList(int fd, int *count);
+extern void drmFreeReservedContextList(drm_context_t *);
+extern int drmSwitchToContext(int fd, drm_context_t context);
+extern int drmDestroyContext(int fd, drm_context_t handle);
+extern int drmCreateDrawable(int fd, drm_drawable_t * handle);
+extern int drmDestroyDrawable(int fd, drm_drawable_t handle);
+extern int drmCtlInstHandler(int fd, int irq);
+extern int drmCtlUninstHandler(int fd);
+extern int drmInstallSIGIOHandler(int fd,
+ void (*f)(int fd,
+ void *oldctx,
+ void *newctx));
+extern int drmRemoveSIGIOHandler(int fd);
+
+/* General user-level programmer's API: authenticated client and/or X */
+extern int drmMap(int fd,
+ drm_handle_t handle,
+ drmSize size,
+ drmAddressPtr address);
+extern int drmUnmap(drmAddress address, drmSize size);
+extern drmBufInfoPtr drmGetBufInfo(int fd);
+extern drmBufMapPtr drmMapBufs(int fd);
+extern int drmUnmapBufs(drmBufMapPtr bufs);
+extern int drmDMA(int fd, drmDMAReqPtr request);
+extern int drmFreeBufs(int fd, int count, int *list);
+extern int drmGetLock(int fd,
+ drm_context_t context,
+ drmLockFlags flags);
+extern int drmUnlock(int fd, drm_context_t context);
+extern int drmFinish(int fd, int context, drmLockFlags flags);
+extern int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id,
+ drm_handle_t * handle);
+
+/* AGP/GART support: X server (root) only */
+extern int drmAgpAcquire(int fd);
+extern int drmAgpRelease(int fd);
+extern int drmAgpEnable(int fd, unsigned long mode);
+extern int drmAgpAlloc(int fd, unsigned long size,
+ unsigned long type, unsigned long *address,
+ unsigned long *handle);
+extern int drmAgpFree(int fd, unsigned long handle);
+extern int drmAgpBind(int fd, unsigned long handle,
+ unsigned long offset);
+extern int drmAgpUnbind(int fd, unsigned long handle);
+
+/* AGP/GART info: authenticated client and/or X */
+extern int drmAgpVersionMajor(int fd);
+extern int drmAgpVersionMinor(int fd);
+extern unsigned long drmAgpGetMode(int fd);
+extern unsigned long drmAgpBase(int fd); /* Physical location */
+extern unsigned long drmAgpSize(int fd); /* Bytes */
+extern unsigned long drmAgpMemoryUsed(int fd);
+extern unsigned long drmAgpMemoryAvail(int fd);
+extern unsigned int drmAgpVendorId(int fd);
+extern unsigned int drmAgpDeviceId(int fd);
+
+/* PCI scatter/gather support: X server (root) only */
+extern int drmScatterGatherAlloc(int fd, unsigned long size,
+ unsigned long *handle);
+extern int drmScatterGatherFree(int fd, unsigned long handle);
+
+extern int drmWaitVBlank(int fd, drmVBlankPtr vbl);
+
+/* Support routines */
+extern int drmError(int err, const char *label);
+extern void *drmMalloc(int size);
+extern void drmFree(void *pt);
+
+/* Hash table routines */
+extern void *drmHashCreate(void);
+extern int drmHashDestroy(void *t);
+extern int drmHashLookup(void *t, unsigned long key, void **value);
+extern int drmHashInsert(void *t, unsigned long key, void *value);
+extern int drmHashDelete(void *t, unsigned long key);
+extern int drmHashFirst(void *t, unsigned long *key, void **value);
+extern int drmHashNext(void *t, unsigned long *key, void **value);
+
+/* PRNG routines */
+extern void *drmRandomCreate(unsigned long seed);
+extern int drmRandomDestroy(void *state);
+extern unsigned long drmRandom(void *state);
+extern double drmRandomDouble(void *state);
+
+/* Skip list routines */
+
+extern void *drmSLCreate(void);
+extern int drmSLDestroy(void *l);
+extern int drmSLLookup(void *l, unsigned long key, void **value);
+extern int drmSLInsert(void *l, unsigned long key, void *value);
+extern int drmSLDelete(void *l, unsigned long key);
+extern int drmSLNext(void *l, unsigned long *key, void **value);
+extern int drmSLFirst(void *l, unsigned long *key, void **value);
+extern void drmSLDump(void *l);
+extern int drmSLLookupNeighbors(void *l, unsigned long key,
+ unsigned long *prev_key, void **prev_value,
+ unsigned long *next_key, void **next_value);
+
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drm.c b/src/mesa/drivers/dri/dri_client/xf86drm.c
new file mode 100644
index 00000000000..dba0f98deba
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drm.c
@@ -0,0 +1,2333 @@
+/**
+ * \file xf86drm.c
+ * User-level interface to DRM device
+ *
+ * \author Rickard E. (Rik) Faith <[email protected]>
+ * \author Kevin E. Martin <[email protected]>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v 1.36 2003/08/24 17:35:35 tsi Exp $ */
+
+#ifdef XFree86Server
+# include "xf86.h"
+# include "xf86_OSproc.h"
+# include "drm.h"
+# include "xf86_ansic.h"
+# define _DRM_MALLOC xalloc
+# define _DRM_FREE xfree
+# ifndef XFree86LOADER
+# include <sys/mman.h>
+# endif
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# define stat_t struct stat
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# ifdef DRM_USE_MALLOC
+# define _DRM_MALLOC malloc
+# define _DRM_FREE free
+# else
+# include <X11/Xlibint.h>
+# define _DRM_MALLOC Xmalloc
+# define _DRM_FREE Xfree
+# endif
+# include "drm.h"
+#endif
+
+/* No longer needed with CVS kernel modules on alpha
+#if defined(__alpha__) && defined(__linux__)
+extern unsigned long _bus_base(void);
+#define BUS_BASE _bus_base()
+#endif
+*/
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "xf86drm.h"
+
+#ifdef __FreeBSD__
+#define DRM_MAJOR 145
+#endif
+
+#ifdef __NetBSD__
+#define DRM_MAJOR 34
+#endif
+
+# ifdef __OpenBSD__
+# define DRM_MAJOR 81
+# endif
+
+#ifndef DRM_MAJOR
+#define DRM_MAJOR 226 /* Linux */
+#endif
+
+#ifndef DRM_MAX_MINOR
+#define DRM_MAX_MINOR 16
+#endif
+
+#ifdef __linux__
+#include <sys/sysmacros.h> /* for makedev() */
+#endif
+
+#ifndef makedev
+ /* This definition needs to be changed on
+ some systems if dev_t is a structure.
+ If there is a header file we can get it
+ from, there would be best. */
+#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
+#endif
+
+#define DRM_MSG_VERBOSITY 3
+
+/**
+ * Output a message to stderr.
+ *
+ * \param format printf() like format string.
+ *
+ * \internal
+ * This function is a wrapper around vfprintf().
+ */
+static void
+drmMsg(const char *format, ...)
+{
+ va_list ap;
+
+#ifndef XFree86Server
+ const char *env;
+ if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose"))
+#endif
+ {
+ va_start(ap, format);
+#ifdef XFree86Server
+ xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
+#else
+ vfprintf(stderr, format, ap);
+#endif
+ va_end(ap);
+ }
+}
+
+static void *drmHashTable = NULL; /* Context switch callbacks */
+
+typedef struct drmHashEntry {
+ int fd;
+ void (*f)(int, void *, void *);
+ void *tagTable;
+} drmHashEntry;
+
+void *drmMalloc(int size)
+{
+ void *pt;
+ if ((pt = _DRM_MALLOC(size))) memset(pt, 0, size);
+ return pt;
+}
+
+void drmFree(void *pt)
+{
+ if (pt) _DRM_FREE(pt);
+}
+
+/* drmStrdup can't use strdup(3), since it doesn't call _DRM_MALLOC... */
+static char *drmStrdup(const char *s)
+{
+ char *retval = NULL;
+
+ if (s) {
+ retval = _DRM_MALLOC(strlen(s)+1);
+ strcpy(retval, s);
+ }
+ return retval;
+}
+
+
+static unsigned long drmGetKeyFromFd(int fd)
+{
+ stat_t st;
+
+ st.st_rdev = 0;
+ fstat(fd, &st);
+ return st.st_rdev;
+}
+
+static drmHashEntry *drmGetEntry(int fd)
+{
+ unsigned long key = drmGetKeyFromFd(fd);
+ void *value;
+ drmHashEntry *entry;
+
+ if (!drmHashTable) drmHashTable = drmHashCreate();
+
+ if (drmHashLookup(drmHashTable, key, &value)) {
+ entry = drmMalloc(sizeof(*entry));
+ entry->fd = fd;
+ entry->f = NULL;
+ entry->tagTable = drmHashCreate();
+ drmHashInsert(drmHashTable, key, entry);
+ } else {
+ entry = value;
+ }
+ return entry;
+}
+
+/**
+ * Compare two busid strings
+ *
+ * \param first
+ * \param second
+ *
+ * \return 1 if matched.
+ *
+ * \internal
+ * This function compares two bus ID strings. It understands the older
+ * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is
+ * domain, b is bus, d is device, f is function.
+ */
+static int drmMatchBusID(const char *id1, const char *id2)
+{
+ /* First, check if the IDs are exactly the same */
+ if (strcasecmp(id1, id2) == 0)
+ return 1;
+
+ /* Try to match old/new-style PCI bus IDs. */
+ if (strncasecmp(id1, "pci", 3) == 0) {
+ int o1, b1, d1, f1;
+ int o2, b2, d2, f2;
+ int ret;
+
+ ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1);
+ if (ret != 4) {
+ o1 = 0;
+ ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1);
+ if (ret != 3)
+ return 0;
+ }
+
+ ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2);
+ if (ret != 4) {
+ o2 = 0;
+ ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2);
+ if (ret != 3)
+ return 0;
+ }
+
+ if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2))
+ return 0;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * Open the DRM device, creating it if necessary.
+ *
+ * \param dev major and minor numbers of the device.
+ * \param minor minor number of the device.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Assembles the device name from \p minor and opens it, creating the device
+ * special file node with the major and minor numbers specified by \p dev and
+ * parent directory if necessary and was called by root.
+ */
+static int drmOpenDevice(long dev, int minor)
+{
+ stat_t st;
+ char buf[64];
+ int fd;
+ mode_t devmode = DRM_DEV_MODE;
+ int isroot = !geteuid();
+#if defined(XFree86Server)
+ uid_t user = DRM_DEV_UID;
+ gid_t group = DRM_DEV_GID;
+#endif
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ drmMsg("drmOpenDevice: node name is %s\n", buf);
+
+#if defined(XFree86Server)
+ devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
+ devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
+ group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID;
+#endif
+
+ if (stat(DRM_DIR_NAME, &st)) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+ chown(DRM_DIR_NAME, 0, 0); /* root:root */
+ chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+ }
+
+ /* Check if the device node exists and create it if necessary. */
+ if (stat(buf, &st)) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+ }
+#if defined(XFree86Server)
+ chown(buf, user, group);
+ chmod(buf, devmode);
+#endif
+
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+ fd, fd < 0 ? strerror(errno) : "OK");
+ if (fd >= 0) return fd;
+
+ /* Check if the device node is not what we expect it to be, and recreate it
+ * and try again if so.
+ */
+ if (st.st_rdev != dev) {
+ if (!isroot) return DRM_ERR_NOT_ROOT;
+ remove(buf);
+ mknod(buf, S_IFCHR | devmode, dev);
+#if defined(XFree86Server)
+ chown(buf, user, group);
+ chmod(buf, devmode);
+#endif
+ }
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+ fd, fd < 0 ? strerror(errno) : "OK");
+ if (fd >= 0) return fd;
+
+ drmMsg("drmOpenDevice: Open failed\n");
+ remove(buf);
+ return -errno;
+}
+
+
+/**
+ * Open the DRM device
+ *
+ * \param minor device minor number.
+ * \param create allow to create the device if set.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
+ * name from \p minor and opens it.
+ */
+static int drmOpenMinor(int minor, int create)
+{
+ int fd;
+ char buf[64];
+
+ if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+
+ sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+ return -errno;
+}
+
+
+/**
+ * Determine whether the DRM kernel driver has been loaded.
+ *
+ * \return 1 if the DRM driver is loaded, 0 otherwise.
+ *
+ * \internal
+ * Determine the presence of the kernel driver by attempting to open the 0
+ * minor and get version information. For backward compatibility with older
+ * Linux implementations, /proc/dri is also checked.
+ */
+int drmAvailable(void)
+{
+ drmVersionPtr version;
+ int retval = 0;
+ int fd;
+
+ if ((fd = drmOpenMinor(0, 1)) < 0) {
+#ifdef __linux__
+ /* Try proc for backward Linux compatibility */
+ if (!access("/proc/dri/0", R_OK)) return 1;
+#endif
+ return 0;
+ }
+
+ if ((version = drmGetVersion(fd))) {
+ retval = 1;
+ drmFreeVersion(version);
+ }
+ close(fd);
+
+ return retval;
+}
+
+
+/**
+ * Open the device by bus ID.
+ *
+ * \param busid bus ID.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
+ * comparing the device bus ID with the one supplied.
+ *
+ * \sa drmOpenMinor() and drmGetBusid().
+ */
+static int drmOpenByBusid(const char *busid)
+{
+ int i;
+ int fd;
+ const char *buf;
+ drmSetVersion sv;
+
+ drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ fd = drmOpenMinor(i, 1);
+ drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
+ if (fd >= 0) {
+ sv.drm_di_major = 1;
+ sv.drm_di_minor = 1;
+ sv.drm_dd_major = -1; /* Don't care */
+ drmSetInterfaceVersion(fd, &sv);
+ buf = drmGetBusid(fd);
+ drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
+ if (buf && drmMatchBusID(buf, busid)) {
+ drmFreeBusid(buf);
+ return fd;
+ }
+ if (buf) drmFreeBusid(buf);
+ close(fd);
+ }
+ }
+ return -1;
+}
+
+
+/**
+ * Open the device by name.
+ *
+ * \param name driver name.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function opens the first minor number that matches the driver name and
+ * isn't already in use. If it's in use it then it will already have a bus ID
+ * assigned.
+ *
+ * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
+ */
+static int drmOpenByName(const char *name)
+{
+ int i;
+ int fd;
+ drmVersionPtr version;
+ char * id;
+
+ if (!drmAvailable()) {
+#if !defined(XFree86Server)
+ return -1;
+#else
+ /* try to load the kernel module now */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+#endif
+ }
+
+ /*
+ * Open the first minor number that matches the driver name and isn't
+ * already in use. If it's in use it will have a busid assigned already.
+ */
+ for (i = 0; i < DRM_MAX_MINOR; i++) {
+ if ((fd = drmOpenMinor(i, 1)) >= 0) {
+ if ((version = drmGetVersion(fd))) {
+ if (!strcmp(version->name, name)) {
+ drmFreeVersion(version);
+ id = drmGetBusid(fd);
+ drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
+ if (!id || !*id) {
+ if (id) {
+ drmFreeBusid(id);
+ }
+ return fd;
+ } else {
+ drmFreeBusid(id);
+ }
+ } else {
+ drmFreeVersion(version);
+ }
+ }
+ close(fd);
+ }
+ }
+
+#ifdef __linux__
+ /* Backward-compatibility /proc support */
+ for (i = 0; i < 8; i++) {
+ char proc_name[64], buf[512];
+ char *driver, *pt, *devstring;
+ int retcode;
+
+ sprintf(proc_name, "/proc/dri/%d/name", i);
+ if ((fd = open(proc_name, 0, 0)) >= 0) {
+ retcode = read(fd, buf, sizeof(buf)-1);
+ close(fd);
+ if (retcode) {
+ buf[retcode-1] = '\0';
+ for (driver = pt = buf; *pt && *pt != ' '; ++pt)
+ ;
+ if (*pt) { /* Device is next */
+ *pt = '\0';
+ if (!strcmp(driver, name)) { /* Match */
+ for (devstring = ++pt; *pt && *pt != ' '; ++pt)
+ ;
+ if (*pt) { /* Found busid */
+ return drmOpenByBusid(++pt);
+ } else { /* No busid */
+ return drmOpenDevice(strtol(devstring, NULL, 0),i);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return -1;
+}
+
+
+/**
+ * Open the DRM device.
+ *
+ * Looks up the specified name and bus ID, and opens the device found. The
+ * entry in /dev/dri is created if necessary and if called by root.
+ *
+ * \param name driver name. Not referenced if bus ID is supplied.
+ * \param busid bus ID. Zero if not known.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
+ * otherwise.
+ */
+int drmOpen(const char *name, const char *busid)
+{
+#ifdef XFree86Server
+ if (!drmAvailable() && name != NULL) {
+ /* try to load the kernel */
+ if (!xf86LoadKernelModule(name)) {
+ ErrorF("[drm] failed to load kernel module \"%s\"\n",
+ name);
+ return -1;
+ }
+ }
+#endif
+
+ if (busid) {
+ int fd;
+
+ fd = drmOpenByBusid(busid);
+ if (fd >= 0)
+ return fd;
+ }
+ if (name)
+ return drmOpenByName(name);
+ return -1;
+}
+
+
+/**
+ * Free the version information returned by drmGetVersion().
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * It frees the memory pointed by \p %v as well as all the non-null strings
+ * pointers in it.
+ */
+void drmFreeVersion(drmVersionPtr v)
+{
+ if (!v) return;
+ if (v->name) drmFree(v->name);
+ if (v->date) drmFree(v->date);
+ if (v->desc) drmFree(v->desc);
+ drmFree(v);
+}
+
+
+/**
+ * Free the non-public version information returned by the kernel.
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
+ * the non-null strings pointers in it.
+ */
+static void drmFreeKernelVersion(drm_version_t *v)
+{
+ if (!v) return;
+ if (v->name) drmFree(v->name);
+ if (v->date) drmFree(v->date);
+ if (v->desc) drmFree(v->desc);
+ drmFree(v);
+}
+
+
+/**
+ * Copy version information.
+ *
+ * \param d destination pointer.
+ * \param s source pointer.
+ *
+ * \internal
+ * Used by drmGetVersion() to translate the information returned by the ioctl
+ * interface in a private structure into the public structure counterpart.
+ */
+static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
+{
+ d->version_major = s->version_major;
+ d->version_minor = s->version_minor;
+ d->version_patchlevel = s->version_patchlevel;
+ d->name_len = s->name_len;
+ d->name = drmStrdup(s->name);
+ d->date_len = s->date_len;
+ d->date = drmStrdup(s->date);
+ d->desc_len = s->desc_len;
+ d->desc = drmStrdup(s->desc);
+}
+
+
+/**
+ * Query the driver version information.
+ *
+ * \param fd file descriptor.
+ *
+ * \return pointer to a drmVersion structure which should be freed with
+ * drmFreeVersion().
+ *
+ * \note Similar information is available via /proc/dri.
+ *
+ * \internal
+ * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
+ * first with zeros to get the string lengths, and then the actually strings.
+ * It also null-terminates them since they might not be already.
+ */
+drmVersionPtr drmGetVersion(int fd)
+{
+ drmVersionPtr retval;
+ drm_version_t *version = drmMalloc(sizeof(*version));
+
+ /* First, get the lengths */
+ version->name_len = 0;
+ version->name = NULL;
+ version->date_len = 0;
+ version->date = NULL;
+ version->desc_len = 0;
+ version->desc = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+ drmFreeKernelVersion(version);
+ return NULL;
+ }
+
+ /* Now, allocate space and get the data */
+ if (version->name_len)
+ version->name = drmMalloc(version->name_len + 1);
+ if (version->date_len)
+ version->date = drmMalloc(version->date_len + 1);
+ if (version->desc_len)
+ version->desc = drmMalloc(version->desc_len + 1);
+
+ if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+ drmMsg("DRM_IOCTL_VERSION: %s\n", strerror(errno));
+ drmFreeKernelVersion(version);
+ return NULL;
+ }
+
+ /* The results might not be null-terminated
+ strings, so terminate them. */
+
+ if (version->name_len) version->name[version->name_len] = '\0';
+ if (version->date_len) version->date[version->date_len] = '\0';
+ if (version->desc_len) version->desc[version->desc_len] = '\0';
+
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ drmCopyVersion(retval, version);
+ drmFreeKernelVersion(version);
+ return retval;
+}
+
+
+/**
+ * Get version information for the DRM user space library.
+ *
+ * This version number is driver independent.
+ *
+ * \param fd file descriptor.
+ *
+ * \return version information.
+ *
+ * \internal
+ * This function allocates and fills a drm_version structure with a hard coded
+ * version number.
+ */
+drmVersionPtr drmGetLibVersion(int fd)
+{
+ drm_version_t *version = drmMalloc(sizeof(*version));
+
+ /* Version history:
+ * revision 1.0.x = original DRM interface with no drmGetLibVersion
+ * entry point and many drm<Device> extensions
+ * revision 1.1.x = added drmCommand entry points for device extensions
+ * added drmGetLibVersion to identify libdrm.a version
+ * revision 1.2.x = added drmSetInterfaceVersion
+ * modified drmOpen to handle both busid and name
+ */
+ version->version_major = 1;
+ version->version_minor = 2;
+ version->version_patchlevel = 0;
+
+ return (drmVersionPtr)version;
+}
+
+
+/**
+ * Free the bus ID information.
+ *
+ * \param busid bus ID information string as given by drmGetBusid().
+ *
+ * \internal
+ * This function is just frees the memory pointed by \p busid.
+ */
+void drmFreeBusid(const char *busid)
+{
+ drmFree((void *)busid);
+}
+
+
+/**
+ * Get the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return bus ID string.
+ *
+ * \internal
+ * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
+ * get the string length and data, passing the arguments in a drm_unique
+ * structure.
+ */
+char *drmGetBusid(int fd)
+{
+ drm_unique_t u;
+
+ u.unique_len = 0;
+ u.unique = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ u.unique = drmMalloc(u.unique_len + 1);
+ if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+ u.unique[u.unique_len] = '\0';
+
+ return u.unique;
+}
+
+
+/**
+ * Set the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ * \param busid bus ID string.
+ *
+ * \return zero on success, negative on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
+ * the arguments in a drm_unique structure.
+ */
+int drmSetBusid(int fd, const char *busid)
+{
+ drm_unique_t u;
+
+ u.unique = (char *)busid;
+ u.unique_len = strlen(busid);
+
+ if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
+ return -errno;
+ }
+ return 0;
+}
+
+int drmGetMagic(int fd, drm_magic_t * magic)
+{
+ drm_auth_t auth;
+
+ *magic = 0;
+ if (ioctl(fd, DRM_IOCTL_GET_MAGIC, &auth)) return -errno;
+ *magic = auth.magic;
+ return 0;
+}
+
+int drmAuthMagic(int fd, drm_magic_t magic)
+{
+ drm_auth_t auth;
+
+ auth.magic = magic;
+ if (ioctl(fd, DRM_IOCTL_AUTH_MAGIC, &auth)) return -errno;
+ return 0;
+}
+
+/**
+ * Specifies a range of memory that is available for mapping by a
+ * non-root process.
+ *
+ * \param fd file descriptor.
+ * \param offset usually the physical address. The actual meaning depends of
+ * the \p type parameter. See below.
+ * \param size of the memory in bytes.
+ * \param type type of the memory to be mapped.
+ * \param flags combination of several flags to modify the function actions.
+ * \param handle will be set to a value that may be used as the offset
+ * parameter for mmap().
+ *
+ * \return zero on success or a negative value on error.
+ *
+ * \par Mapping the frame buffer
+ * For the frame buffer
+ * - \p offset will be the physical address of the start of the frame buffer,
+ * - \p size will be the size of the frame buffer in bytes, and
+ * - \p type will be DRM_FRAME_BUFFER.
+ *
+ * \par
+ * The area mapped will be uncached. If MTRR support is available in the
+ * kernel, the frame buffer area will be set to write combining.
+ *
+ * \par Mapping the MMIO register area
+ * For the MMIO register area,
+ * - \p offset will be the physical address of the start of the register area,
+ * - \p size will be the size of the register area bytes, and
+ * - \p type will be DRM_REGISTERS.
+ * \par
+ * The area mapped will be uncached.
+ *
+ * \par Mapping the SAREA
+ * For the SAREA,
+ * - \p offset will be ignored and should be set to zero,
+ * - \p size will be the desired size of the SAREA in bytes,
+ * - \p type will be DRM_SHM.
+ *
+ * \par
+ * A shared memory area of the requested size will be created and locked in
+ * kernel memory. This area may be mapped into client-space by using the handle
+ * returned.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
+ * the arguments in a drm_map structure.
+ */
+int drmAddMap(int fd,
+ drm_handle_t offset,
+ drmSize size,
+ drmMapType type,
+ drmMapFlags flags,
+ drm_handle_t * handle)
+{
+ drm_map_t map;
+
+ map.offset = offset;
+/* No longer needed with CVS kernel modules on alpha
+#ifdef __alpha__
+ if (type != DRM_SHM)
+ map.offset += BUS_BASE;
+#endif
+*/
+ map.size = size;
+ map.handle = 0;
+ map.type = type;
+ map.flags = flags;
+ if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
+ if (handle) *handle = (drm_handle_t)map.handle;
+ return 0;
+}
+
+int drmRmMap(int fd, drm_handle_t handle)
+{
+ drm_map_t map;
+
+ map.handle = (void *)handle;
+
+ if(ioctl(fd, DRM_IOCTL_RM_MAP, &map)) return -errno;
+ return 0;
+}
+
+/**
+ * Make buffers available for DMA transfers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers.
+ * \param size size of each buffer.
+ * \param flags buffer allocation flags.
+ * \param agp_offset offset in the AGP aperture
+ *
+ * \return number of buffers allocated, negative on error.
+ *
+ * \internal
+ * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
+ *
+ * \sa drm_buf_desc.
+ */
+int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+ int agp_offset)
+{
+ drm_buf_desc_t request;
+
+ request.count = count;
+ request.size = size;
+ request.low_mark = 0;
+ request.high_mark = 0;
+ request.flags = flags;
+ request.agp_start = agp_offset;
+
+ if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
+ return request.count;
+}
+
+int drmMarkBufs(int fd, double low, double high)
+{
+ drm_buf_info_t info;
+ int i;
+
+ info.count = 0;
+ info.list = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return -EINVAL;
+
+ if (!info.count) return -EINVAL;
+
+ if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+ return -ENOMEM;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+ int retval = -errno;
+ drmFree(info.list);
+ return retval;
+ }
+
+ for (i = 0; i < info.count; i++) {
+ info.list[i].low_mark = low * info.list[i].count;
+ info.list[i].high_mark = high * info.list[i].count;
+ if (ioctl(fd, DRM_IOCTL_MARK_BUFS, &info.list[i])) {
+ int retval = -errno;
+ drmFree(info.list);
+ return retval;
+ }
+ }
+ drmFree(info.list);
+
+ return 0;
+}
+
+/**
+ * Free buffers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers to free.
+ * \param list list of buffers to be freed.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note This function is primarily used for debugging.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
+ * the arguments in a drm_buf_free structure.
+ */
+int drmFreeBufs(int fd, int count, int *list)
+{
+ drm_buf_free_t request;
+
+ request.count = count;
+ request.list = list;
+ if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Close the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \internal
+ * This function closes the file descriptor.
+ */
+int drmClose(int fd)
+{
+ unsigned long key = drmGetKeyFromFd(fd);
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ drmHashDestroy(entry->tagTable);
+ entry->fd = 0;
+ entry->f = NULL;
+ entry->tagTable = NULL;
+
+ drmHashDelete(drmHashTable, key);
+ drmFree(entry);
+
+ return close(fd);
+}
+
+
+/**
+ * Map a region of memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle returned by drmAddMap().
+ * \param size size in bytes. Must match the size used by drmAddMap().
+ * \param address will contain the user-space virtual address where the mapping
+ * begins.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for mmap().
+ */
+int drmMap(int fd,
+ drm_handle_t handle,
+ drmSize size,
+ drmAddressPtr address)
+{
+ static unsigned long pagesize_mask = 0;
+
+ if (fd < 0) return -EINVAL;
+
+ if (!pagesize_mask)
+ pagesize_mask = getpagesize() - 1;
+
+ size = (size + pagesize_mask) & ~pagesize_mask;
+
+ *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
+ if (*address == MAP_FAILED) return -errno;
+ return 0;
+}
+
+
+/**
+ * Unmap mappings obtained with drmMap().
+ *
+ * \param address address as given by drmMap().
+ * \param size size in bytes. Must match the size used by drmMap().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for unmap().
+ */
+int drmUnmap(drmAddress address, drmSize size)
+{
+ return munmap(address, size);
+}
+
+drmBufInfoPtr drmGetBufInfo(int fd)
+{
+ drm_buf_info_t info;
+ drmBufInfoPtr retval;
+ int i;
+
+ info.count = 0;
+ info.list = NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) return NULL;
+
+ if (info.count) {
+ if (!(info.list = drmMalloc(info.count * sizeof(*info.list))))
+ return NULL;
+
+ if (ioctl(fd, DRM_IOCTL_INFO_BUFS, &info)) {
+ drmFree(info.list);
+ return NULL;
+ }
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ retval->count = info.count;
+ retval->list = drmMalloc(info.count * sizeof(*retval->list));
+ for (i = 0; i < info.count; i++) {
+ retval->list[i].count = info.list[i].count;
+ retval->list[i].size = info.list[i].size;
+ retval->list[i].low_mark = info.list[i].low_mark;
+ retval->list[i].high_mark = info.list[i].high_mark;
+ }
+ drmFree(info.list);
+ return retval;
+ }
+ return NULL;
+}
+
+/**
+ * Map all DMA buffers into client-virtual space.
+ *
+ * \param fd file descriptor.
+ *
+ * \return a pointer to a ::drmBufMap structure.
+ *
+ * \note The client may not use these buffers until obtaining buffer indices
+ * with drmDMA().
+ *
+ * \internal
+ * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
+ * information about the buffers in a drm_buf_map structure into the
+ * client-visible data structures.
+ */
+drmBufMapPtr drmMapBufs(int fd)
+{
+ drm_buf_map_t bufs;
+ drmBufMapPtr retval;
+ int i;
+
+ bufs.count = 0;
+ bufs.list = NULL;
+ bufs.virtual = NULL;
+ if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
+
+ if (!bufs.count) return NULL;
+
+ if (!(bufs.list = drmMalloc(bufs.count * sizeof(*bufs.list))))
+ return NULL;
+
+ if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
+ drmFree(bufs.list);
+ return NULL;
+ }
+ /* Now, copy it all back into the
+ client-visible data structure... */
+ retval = drmMalloc(sizeof(*retval));
+ retval->count = bufs.count;
+ retval->list = drmMalloc(bufs.count * sizeof(*retval->list));
+ for (i = 0; i < bufs.count; i++) {
+ retval->list[i].idx = bufs.list[i].idx;
+ retval->list[i].total = bufs.list[i].total;
+ retval->list[i].used = 0;
+ retval->list[i].address = bufs.list[i].address;
+ }
+
+ drmFree(bufs.list);
+
+ return retval;
+}
+
+
+/**
+ * Unmap buffers allocated with drmMapBufs().
+ *
+ * \return zero on success, or negative value on failure.
+ *
+ * \internal
+ * Calls munmap() for every buffer stored in \p bufs and frees the
+ * memory allocated by drmMapBufs().
+ */
+int drmUnmapBufs(drmBufMapPtr bufs)
+{
+ int i;
+
+ for (i = 0; i < bufs->count; i++) {
+ munmap(bufs->list[i].address, bufs->list[i].total);
+ }
+
+ drmFree(bufs->list);
+ drmFree(bufs);
+
+ return 0;
+}
+
+
+#define DRM_DMA_RETRY 16
+
+/**
+ * Reserve DMA buffers.
+ *
+ * \param fd file descriptor.
+ * \param request
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * Assemble the arguments into a drm_dma structure and keeps issuing the
+ * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
+ */
+int drmDMA(int fd, drmDMAReqPtr request)
+{
+ drm_dma_t dma;
+ int ret, i = 0;
+
+ /* Copy to hidden structure */
+ dma.context = request->context;
+ dma.send_count = request->send_count;
+ dma.send_indices = request->send_list;
+ dma.send_sizes = request->send_sizes;
+ dma.flags = request->flags;
+ dma.request_count = request->request_count;
+ dma.request_size = request->request_size;
+ dma.request_indices = request->request_list;
+ dma.request_sizes = request->request_sizes;
+ dma.granted_count = 0;
+
+ do {
+ ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
+ } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
+
+ if ( ret == 0 ) {
+ request->granted_count = dma.granted_count;
+ return 0;
+ } else {
+ return -errno;
+ }
+}
+
+
+/**
+ * Obtain heavyweight hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * \param flags flags that determine the sate of the hardware when the function
+ * returns.
+ *
+ * \return always zero.
+ *
+ * \internal
+ * This function translates the arguments into a drm_lock structure and issue
+ * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
+ */
+int drmGetLock(int fd, drm_context_t context, drmLockFlags flags)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
+ if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
+ if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
+ if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
+ if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+ if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+
+ while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
+ ;
+ return 0;
+}
+
+/**
+ * Release the hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
+ * argument in a drm_lock structure.
+ */
+int drmUnlock(int fd, drm_context_t context)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ return ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
+}
+
+drm_context_t * drmGetReservedContextList(int fd, int *count)
+{
+ drm_ctx_res_t res;
+ drm_ctx_t *list;
+ drm_context_t * retval;
+ int i;
+
+ res.count = 0;
+ res.contexts = NULL;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+ if (!res.count) return NULL;
+
+ if (!(list = drmMalloc(res.count * sizeof(*list)))) return NULL;
+ if (!(retval = drmMalloc(res.count * sizeof(*retval)))) {
+ drmFree(list);
+ return NULL;
+ }
+
+ res.contexts = list;
+ if (ioctl(fd, DRM_IOCTL_RES_CTX, &res)) return NULL;
+
+ for (i = 0; i < res.count; i++) retval[i] = list[i].handle;
+ drmFree(list);
+
+ *count = res.count;
+ return retval;
+}
+
+void drmFreeReservedContextList(drm_context_t * pt)
+{
+ drmFree(pt);
+}
+
+/**
+ * Create context.
+ *
+ * Used by the X server during GLXContext initialization. This causes
+ * per-context kernel-level resources to be allocated.
+ *
+ * \param fd file descriptor.
+ * \param handle is set on success. To be used by the client when requesting DMA
+ * dispatch with drmDMA().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmCreateContext(int fd, drm_context_t * handle)
+{
+ drm_ctx_t ctx;
+
+ ctx.flags = 0; /* Modified with functions below */
+ if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
+ *handle = ctx.handle;
+ return 0;
+}
+
+int drmSwitchToContext(int fd, drm_context_t context)
+{
+ drm_ctx_t ctx;
+
+ ctx.handle = context;
+ if (ioctl(fd, DRM_IOCTL_SWITCH_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmSetContextFlags(int fd, drm_context_t context, drm_context_tFlags flags)
+{
+ drm_ctx_t ctx;
+
+ /* Context preserving means that no context
+ switched are done between DMA buffers
+ from one context and the next. This is
+ suitable for use in the X server (which
+ promises to maintain hardware context,
+ or in the client-side library when
+ buffers are swapped on behalf of two
+ threads. */
+ ctx.handle = context;
+ ctx.flags = 0;
+ if (flags & DRM_CONTEXT_PRESERVED) ctx.flags |= _DRM_CONTEXT_PRESERVED;
+ if (flags & DRM_CONTEXT_2DONLY) ctx.flags |= _DRM_CONTEXT_2DONLY;
+ if (ioctl(fd, DRM_IOCTL_MOD_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmGetContextFlags(int fd, drm_context_t context, drm_context_tFlagsPtr flags)
+{
+ drm_ctx_t ctx;
+
+ ctx.handle = context;
+ if (ioctl(fd, DRM_IOCTL_GET_CTX, &ctx)) return -errno;
+ *flags = 0;
+ if (ctx.flags & _DRM_CONTEXT_PRESERVED) *flags |= DRM_CONTEXT_PRESERVED;
+ if (ctx.flags & _DRM_CONTEXT_2DONLY) *flags |= DRM_CONTEXT_2DONLY;
+ return 0;
+}
+
+/**
+ * Destroy context.
+ *
+ * Free any kernel-level resources allocated with drmCreateContext() associated
+ * with the context.
+ *
+ * \param fd file descriptor.
+ * \param handle handle given by drmCreateContext().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmDestroyContext(int fd, drm_context_t handle)
+{
+ drm_ctx_t ctx;
+ ctx.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
+ return 0;
+}
+
+int drmCreateDrawable(int fd, drm_drawable_t * handle)
+{
+ drm_draw_t draw;
+ if (ioctl(fd, DRM_IOCTL_ADD_DRAW, &draw)) return -errno;
+ *handle = draw.handle;
+ return 0;
+}
+
+int drmDestroyDrawable(int fd, drm_drawable_t handle)
+{
+ drm_draw_t draw;
+ draw.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_RM_DRAW, &draw)) return -errno;
+ return 0;
+}
+
+/**
+ * Acquire the AGP device.
+ *
+ * Must be called before any of the other AGP related calls.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
+ */
+int drmAgpAcquire(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Release the AGP device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
+ */
+int drmAgpRelease(int fd)
+{
+ if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Set the AGP mode.
+ *
+ * \param fd file descriptor.
+ * \param mode AGP mode.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
+ * argument in a drm_agp_mode structure.
+ */
+int drmAgpEnable(int fd, unsigned long mode)
+{
+ drm_agp_mode_t m;
+
+ m.mode = mode;
+ if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Allocate a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param size requested memory size in bytes. Will be rounded to page boundary.
+ * \param type type of memory to allocate.
+ * \param address if not zero, will be set to the physical address of the
+ * allocated memory.
+ * \param handle on success will be set to a handle of the allocated memory.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
+ * arguments in a drm_agp_buffer structure.
+ */
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+ unsigned long *address, unsigned long *handle)
+{
+ drm_agp_buffer_t b;
+
+ *handle = DRM_AGP_NO_HANDLE;
+ b.size = size;
+ b.handle = 0;
+ b.type = type;
+ if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
+ if (address != 0UL) *address = b.physical;
+ *handle = b.handle;
+ return 0;
+}
+
+
+/**
+ * Free a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
+ * argument in a drm_agp_buffer structure.
+ */
+int drmAgpFree(int fd, unsigned long handle)
+{
+ drm_agp_buffer_t b;
+
+ b.size = 0;
+ b.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Bind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * \param offset offset in bytes. It will round to page boundary.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
+ * argument in a drm_agp_binding structure.
+ */
+int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = offset;
+ if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Unbind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
+ * the argument in a drm_agp_binding structure.
+ */
+int drmAgpUnbind(int fd, unsigned long handle)
+{
+ drm_agp_binding_t b;
+
+ b.handle = handle;
+ b.offset = 0;
+ if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Get AGP driver major version number.
+ *
+ * \param fd file descriptor.
+ *
+ * \return major version number on success, or a negative value on failure..
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMajor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_major;
+}
+
+
+/**
+ * Get AGP driver minor version number.
+ *
+ * \param fd file descriptor.
+ *
+ * \return minor version number on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMinor(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+ return i.agp_version_minor;
+}
+
+
+/**
+ * Get AGP mode.
+ *
+ * \param fd file descriptor.
+ *
+ * \return mode on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpGetMode(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.mode;
+}
+
+
+/**
+ * Get AGP aperture base.
+ *
+ * \param fd file descriptor.
+ *
+ * \return aperture base on success, zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpBase(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_base;
+}
+
+
+/**
+ * Get AGP aperture size.
+ *
+ * \param fd file descriptor.
+ *
+ * \return aperture size on success, zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpSize(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.aperture_size;
+}
+
+
+/**
+ * Get used AGP memory.
+ *
+ * \param fd file descriptor.
+ *
+ * \return memory used on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryUsed(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_used;
+}
+
+
+/**
+ * Get available AGP memory.
+ *
+ * \param fd file descriptor.
+ *
+ * \return memory available on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryAvail(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.memory_allowed;
+}
+
+
+/**
+ * Get hardware vendor ID.
+ *
+ * \param fd file descriptor.
+ *
+ * \return vendor ID on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpVendorId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_vendor;
+}
+
+
+/**
+ * Get hardware device ID.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or zero on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpDeviceId(int fd)
+{
+ drm_agp_info_t i;
+
+ if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+ return i.id_device;
+}
+
+int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
+{
+ drm_scatter_gather_t sg;
+
+ *handle = 0;
+ sg.size = size;
+ sg.handle = 0;
+ if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+ *handle = sg.handle;
+ return 0;
+}
+
+int drmScatterGatherFree(int fd, unsigned long handle)
+{
+ drm_scatter_gather_t sg;
+
+ sg.size = 0;
+ sg.handle = handle;
+ if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+ return 0;
+}
+
+/**
+ * Wait for VBLANK.
+ *
+ * \param fd file descriptor.
+ * \param vbl pointer to a drmVBlank structure.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
+ */
+int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+{
+ int ret;
+
+ do {
+ ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+ vbl->request.type &= ~DRM_VBLANK_RELATIVE;
+ } while (ret && errno == EINTR);
+
+ return ret;
+}
+
+int drmError(int err, const char *label)
+{
+ switch (err) {
+ case DRM_ERR_NO_DEVICE: fprintf(stderr, "%s: no device\n", label); break;
+ case DRM_ERR_NO_ACCESS: fprintf(stderr, "%s: no access\n", label); break;
+ case DRM_ERR_NOT_ROOT: fprintf(stderr, "%s: not root\n", label); break;
+ case DRM_ERR_INVALID: fprintf(stderr, "%s: invalid args\n", label);break;
+ default:
+ if (err < 0) err = -err;
+ fprintf( stderr, "%s: error %d (%s)\n", label, err, strerror(err) );
+ break;
+ }
+
+ return 1;
+}
+
+/**
+ * Install IRQ handler.
+ *
+ * \param fd file descriptor.
+ * \param irq IRQ number.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlInstHandler(int fd, int irq)
+{
+ drm_control_t ctl;
+
+ ctl.func = DRM_INST_HANDLER;
+ ctl.irq = irq;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ return 0;
+}
+
+
+/**
+ * Uninstall IRQ handler.
+ *
+ * \param fd file descriptor.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlUninstHandler(int fd)
+{
+ drm_control_t ctl;
+
+ ctl.func = DRM_UNINST_HANDLER;
+ ctl.irq = 0;
+ if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+ return 0;
+}
+
+int drmFinish(int fd, int context, drmLockFlags flags)
+{
+ drm_lock_t lock;
+
+ lock.context = context;
+ lock.flags = 0;
+ if (flags & DRM_LOCK_READY) lock.flags |= _DRM_LOCK_READY;
+ if (flags & DRM_LOCK_QUIESCENT) lock.flags |= _DRM_LOCK_QUIESCENT;
+ if (flags & DRM_LOCK_FLUSH) lock.flags |= _DRM_LOCK_FLUSH;
+ if (flags & DRM_LOCK_FLUSH_ALL) lock.flags |= _DRM_LOCK_FLUSH_ALL;
+ if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+ if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+ if (ioctl(fd, DRM_IOCTL_FINISH, &lock)) return -errno;
+ return 0;
+}
+
+/**
+ * Get IRQ from bus ID.
+ *
+ * \param fd file descriptor.
+ * \param busnum bus number.
+ * \param devnum device number.
+ * \param funcnum function number.
+ *
+ * \return IRQ number on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
+ * arguments in a drm_irq_busid structure.
+ */
+int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
+{
+ drm_irq_busid_t p;
+
+ p.busnum = busnum;
+ p.devnum = devnum;
+ p.funcnum = funcnum;
+ if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
+ return p.irq;
+}
+
+int drmAddContextTag(int fd, drm_context_t context, void *tag)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ if (drmHashInsert(entry->tagTable, context, tag)) {
+ drmHashDelete(entry->tagTable, context);
+ drmHashInsert(entry->tagTable, context, tag);
+ }
+ return 0;
+}
+
+int drmDelContextTag(int fd, drm_context_t context)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ return drmHashDelete(entry->tagTable, context);
+}
+
+void *drmGetContextTag(int fd, drm_context_t context)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+ void *value;
+
+ if (drmHashLookup(entry->tagTable, context, &value)) return NULL;
+
+ return value;
+}
+
+int drmAddContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t handle)
+{
+ drm_ctx_priv_map_t map;
+
+ map.ctx_id = ctx_id;
+ map.handle = (void *)handle;
+
+ if (ioctl(fd, DRM_IOCTL_SET_SAREA_CTX, &map)) return -errno;
+ return 0;
+}
+
+int drmGetContextPrivateMapping(int fd, drm_context_t ctx_id, drm_handle_t * handle)
+{
+ drm_ctx_priv_map_t map;
+
+ map.ctx_id = ctx_id;
+
+ if (ioctl(fd, DRM_IOCTL_GET_SAREA_CTX, &map)) return -errno;
+ if (handle) *handle = (drm_handle_t)map.handle;
+
+ return 0;
+}
+
+int drmGetMap(int fd, int idx, drm_handle_t *offset, drmSize *size,
+ drmMapType *type, drmMapFlags *flags, drm_handle_t *handle,
+ int *mtrr)
+{
+ drm_map_t map;
+
+ map.offset = idx;
+ if (ioctl(fd, DRM_IOCTL_GET_MAP, &map)) return -errno;
+ *offset = map.offset;
+ *size = map.size;
+ *type = map.type;
+ *flags = map.flags;
+ *handle = (unsigned long)map.handle;
+ *mtrr = map.mtrr;
+ return 0;
+}
+
+int drmGetClient(int fd, int idx, int *auth, int *pid, int *uid,
+ unsigned long *magic, unsigned long *iocs)
+{
+ drm_client_t client;
+
+ client.idx = idx;
+ if (ioctl(fd, DRM_IOCTL_GET_CLIENT, &client)) return -errno;
+ *auth = client.auth;
+ *pid = client.pid;
+ *uid = client.uid;
+ *magic = client.magic;
+ *iocs = client.iocs;
+ return 0;
+}
+
+int drmGetStats(int fd, drmStatsT *stats)
+{
+ drm_stats_t s;
+ int i;
+
+ if (ioctl(fd, DRM_IOCTL_GET_STATS, &s)) return -errno;
+
+ stats->count = 0;
+ memset(stats, 0, sizeof(*stats));
+ if (s.count > sizeof(stats->data)/sizeof(stats->data[0]))
+ return -1;
+
+#define SET_VALUE \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%8.8s"; \
+ stats->data[i].isvalue = 1; \
+ stats->data[i].verbose = 0
+
+#define SET_COUNT \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "kgm"; \
+ stats->data[i].mult = 1000; \
+ stats->data[i].verbose = 0
+
+#define SET_BYTE \
+ stats->data[i].long_format = "%-20.20s"; \
+ stats->data[i].rate_format = "%5.5s"; \
+ stats->data[i].isvalue = 0; \
+ stats->data[i].mult_names = "KGM"; \
+ stats->data[i].mult = 1024; \
+ stats->data[i].verbose = 0
+
+
+ stats->count = s.count;
+ for (i = 0; i < s.count; i++) {
+ stats->data[i].value = s.data[i].value;
+ switch (s.data[i].type) {
+ case _DRM_STAT_LOCK:
+ stats->data[i].long_name = "Lock";
+ stats->data[i].rate_name = "Lock";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_OPENS:
+ stats->data[i].long_name = "Opens";
+ stats->data[i].rate_name = "O";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_CLOSES:
+ stats->data[i].long_name = "Closes";
+ stats->data[i].rate_name = "Lock";
+ SET_COUNT;
+ stats->data[i].verbose = 1;
+ break;
+ case _DRM_STAT_IOCTLS:
+ stats->data[i].long_name = "Ioctls";
+ stats->data[i].rate_name = "Ioc/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_LOCKS:
+ stats->data[i].long_name = "Locks";
+ stats->data[i].rate_name = "Lck/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_UNLOCKS:
+ stats->data[i].long_name = "Unlocks";
+ stats->data[i].rate_name = "Unl/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_IRQ:
+ stats->data[i].long_name = "IRQs";
+ stats->data[i].rate_name = "IRQ/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_PRIMARY:
+ stats->data[i].long_name = "Primary Bytes";
+ stats->data[i].rate_name = "PB/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_SECONDARY:
+ stats->data[i].long_name = "Secondary Bytes";
+ stats->data[i].rate_name = "SB/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_DMA:
+ stats->data[i].long_name = "DMA";
+ stats->data[i].rate_name = "DMA/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_SPECIAL:
+ stats->data[i].long_name = "Special DMA";
+ stats->data[i].rate_name = "dma/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_MISSED:
+ stats->data[i].long_name = "Miss";
+ stats->data[i].rate_name = "Ms/s";
+ SET_COUNT;
+ break;
+ case _DRM_STAT_VALUE:
+ stats->data[i].long_name = "Value";
+ stats->data[i].rate_name = "Value";
+ SET_VALUE;
+ break;
+ case _DRM_STAT_BYTE:
+ stats->data[i].long_name = "Bytes";
+ stats->data[i].rate_name = "B/s";
+ SET_BYTE;
+ break;
+ case _DRM_STAT_COUNT:
+ default:
+ stats->data[i].long_name = "Count";
+ stats->data[i].rate_name = "Cnt/s";
+ SET_COUNT;
+ break;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Issue a set-version ioctl.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read-write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmSetInterfaceVersion(int fd, drmSetVersion *version )
+{
+ int retcode = 0;
+ drm_set_version_t sv;
+
+ sv.drm_di_major = version->drm_di_major;
+ sv.drm_di_minor = version->drm_di_minor;
+ sv.drm_dd_major = version->drm_dd_major;
+ sv.drm_dd_minor = version->drm_dd_minor;
+
+ if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) {
+ retcode = -errno;
+ }
+
+ version->drm_di_major = sv.drm_di_major;
+ version->drm_di_minor = sv.drm_di_minor;
+ version->drm_dd_major = sv.drm_dd_major;
+ version->drm_dd_minor = sv.drm_dd_minor;
+
+ return retcode;
+}
+
+/**
+ * Send a device-specific command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandNone(int fd, unsigned long drmCommandIndex)
+{
+ void *data = NULL; /* dummy */
+ unsigned long request;
+
+ request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific read command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data destination pointer of the data to be read.
+ * \param size size of the data to be read.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be written.
+ * \param size size of the data to be written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+
+/**
+ * Send a device-specific read-write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ *
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read-write ioctl given by
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+ void *data, unsigned long size )
+{
+ unsigned long request;
+
+ request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE,
+ DRM_COMMAND_BASE + drmCommandIndex, size);
+
+ if (ioctl(fd, request, data)) {
+ return -errno;
+ }
+ return 0;
+}
+
+#if defined(XFree86Server)
+static void drmSIGIOHandler(int interrupt, void *closure)
+{
+ unsigned long key;
+ void *value;
+ ssize_t count;
+ drm_ctx_t ctx;
+ typedef void (*_drmCallback)(int, void *, void *);
+ char buf[256];
+ drm_context_t old;
+ drm_context_t new;
+ void *oldctx;
+ void *newctx;
+ char *pt;
+ drmHashEntry *entry;
+
+ if (!drmHashTable) return;
+ if (drmHashFirst(drmHashTable, &key, &value)) {
+ entry = value;
+ do {
+#if 0
+ fprintf(stderr, "Trying %d\n", entry->fd);
+#endif
+ if ((count = read(entry->fd, buf, sizeof(buf))) > 0) {
+ buf[count] = '\0';
+#if 0
+ fprintf(stderr, "Got %s\n", buf);
+#endif
+
+ for (pt = buf; *pt != ' '; ++pt); /* Find first space */
+ ++pt;
+ old = strtol(pt, &pt, 0);
+ new = strtol(pt, NULL, 0);
+ oldctx = drmGetContextTag(entry->fd, old);
+ newctx = drmGetContextTag(entry->fd, new);
+#if 0
+ fprintf(stderr, "%d %d %p %p\n", old, new, oldctx, newctx);
+#endif
+ ((_drmCallback)entry->f)(entry->fd, oldctx, newctx);
+ ctx.handle = new;
+ ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
+ }
+ } while (drmHashNext(drmHashTable, &key, &value));
+ }
+}
+
+int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *))
+{
+ drmHashEntry *entry;
+
+ entry = drmGetEntry(fd);
+ entry->f = f;
+
+ return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
+}
+
+int drmRemoveSIGIOHandler(int fd)
+{
+ drmHashEntry *entry = drmGetEntry(fd);
+
+ entry->f = NULL;
+
+ return xf86RemoveSIGIOHandler(fd);
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmHash.c b/src/mesa/drivers/dri/dri_client/xf86drmHash.c
new file mode 100644
index 00000000000..5f89d540dc2
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmHash.c
@@ -0,0 +1,433 @@
+/* xf86drmHash.c -- Small hash table support for integer -> integer mapping
+ * Created: Sun Apr 18 09:35:45 1999 by [email protected]
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors: Rickard E. (Rik) Faith <[email protected]>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmHash.c,v 1.4 2001/03/21 18:08:54 dawes Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward implementation of a fixed-sized
+ * hash table using self-organizing linked lists [Knuth73, pp. 398-399] for
+ * collision resolution. There are two potentially interesting things
+ * about this implementation:
+ *
+ * 1) The table is power-of-two sized. Prime sized tables are more
+ * traditional, but do not have a significant advantage over power-of-two
+ * sized table, especially when double hashing is not used for collision
+ * resolution.
+ *
+ * 2) The hash computation uses a table of random integers [Hanson97,
+ * pp. 39-41].
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * With a table size of 512, the current implementation is sufficient for a
+ * few hundred keys. Since this is well above the expected size of the
+ * tables for which this implementation was designed, the implementation of
+ * dynamic hash tables was postponed until the need arises. A common (and
+ * naive) approach to dynamic hash table implementation simply creates a
+ * new hash table when necessary, rehashes all the data into the new table,
+ * and destroys the old table. The approach in [Larson88] is superior in
+ * two ways: 1) only a portion of the table is expanded when needed,
+ * distributing the expansion cost over several insertions, and 2) portions
+ * of the table can be locked, enabling a scalable thread-safe
+ * implementation.
+ *
+ * REFERENCES
+ *
+ * [Hanson97] David R. Hanson. C Interfaces and Implementations:
+ * Techniques for Creating Reusable Software. Reading, Massachusetts:
+ * Addison-Wesley, 1997.
+ *
+ * [Knuth73] Donald E. Knuth. The Art of Computer Programming. Volume 3:
+ * Sorting and Searching. Reading, Massachusetts: Addison-Wesley, 1973.
+ *
+ * [Larson88] Per-Ake Larson. "Dynamic Hash Tables". CACM 31(4), April
+ * 1988, pp. 446-457.
+ *
+ */
+
+#define HASH_MAIN 0
+
+#if HASH_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+# include "xf86.h"
+# include "xf86_ansic.h"
+# else
+# include <stdio.h>
+# include <stdlib.h>
+# endif
+#endif
+
+#define HASH_MAGIC 0xdeadbeef
+#define HASH_DEBUG 0
+#define HASH_SIZE 512 /* Good for about 100 entries */
+ /* If you change this value, you probably
+ have to change the HashHash hashing
+ function! */
+
+#if HASH_MAIN
+#define HASH_ALLOC malloc
+#define HASH_FREE free
+#define HASH_RANDOM_DECL
+#define HASH_RANDOM_INIT(seed) srandom(seed)
+#define HASH_RANDOM random()
+#else
+#define HASH_ALLOC drmMalloc
+#define HASH_FREE drmFree
+#define HASH_RANDOM_DECL void *state
+#define HASH_RANDOM_INIT(seed) state = drmRandomCreate(seed)
+#define HASH_RANDOM drmRandom(state)
+
+#endif
+
+typedef struct HashBucket {
+ unsigned long key;
+ void *value;
+ struct HashBucket *next;
+} HashBucket, *HashBucketPtr;
+
+typedef struct HashTable {
+ unsigned long magic;
+ unsigned long entries;
+ unsigned long hits; /* At top of linked list */
+ unsigned long partials; /* Not at top of linked list */
+ unsigned long misses; /* Not in table */
+ HashBucketPtr buckets[HASH_SIZE];
+ int p0;
+ HashBucketPtr p1;
+} HashTable, *HashTablePtr;
+
+#if HASH_MAIN
+extern void *drmHashCreate(void);
+extern int drmHashDestroy(void *t);
+extern int drmHashLookup(void *t, unsigned long key, unsigned long *value);
+extern int drmHashInsert(void *t, unsigned long key, unsigned long value);
+extern int drmHashDelete(void *t, unsigned long key);
+#endif
+
+static unsigned long HashHash(unsigned long key)
+{
+ unsigned long hash = 0;
+ unsigned long tmp = key;
+ static int init = 0;
+ static unsigned long scatter[256];
+ int i;
+
+ if (!init) {
+ HASH_RANDOM_DECL;
+ HASH_RANDOM_INIT(37);
+ for (i = 0; i < 256; i++) scatter[i] = HASH_RANDOM;
+ ++init;
+ }
+
+ while (tmp) {
+ hash = (hash << 1) + scatter[tmp & 0xff];
+ tmp >>= 8;
+ }
+
+ hash %= HASH_SIZE;
+#if HASH_DEBUG
+ printf( "Hash(%d) = %d\n", key, hash);
+#endif
+ return hash;
+}
+
+void *drmHashCreate(void)
+{
+ HashTablePtr table;
+ int i;
+
+ table = HASH_ALLOC(sizeof(*table));
+ if (!table) return NULL;
+ table->magic = HASH_MAGIC;
+ table->entries = 0;
+ table->hits = 0;
+ table->partials = 0;
+ table->misses = 0;
+
+ for (i = 0; i < HASH_SIZE; i++) table->buckets[i] = NULL;
+ return table;
+}
+
+int drmHashDestroy(void *t)
+{
+ HashTablePtr table = (HashTablePtr)t;
+ HashBucketPtr bucket;
+ HashBucketPtr next;
+ int i;
+
+ if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+ for (i = 0; i < HASH_SIZE; i++) {
+ for (bucket = table->buckets[i]; bucket;) {
+ next = bucket->next;
+ HASH_FREE(bucket);
+ bucket = next;
+ }
+ }
+ HASH_FREE(table);
+ return 0;
+}
+
+/* Find the bucket and organize the list so that this bucket is at the
+ top. */
+
+static HashBucketPtr HashFind(HashTablePtr table,
+ unsigned long key, unsigned long *h)
+{
+ unsigned long hash = HashHash(key);
+ HashBucketPtr prev = NULL;
+ HashBucketPtr bucket;
+
+ if (h) *h = hash;
+
+ for (bucket = table->buckets[hash]; bucket; bucket = bucket->next) {
+ if (bucket->key == key) {
+ if (prev) {
+ /* Organize */
+ prev->next = bucket->next;
+ bucket->next = table->buckets[hash];
+ table->buckets[hash] = bucket;
+ ++table->partials;
+ } else {
+ ++table->hits;
+ }
+ return bucket;
+ }
+ prev = bucket;
+ }
+ ++table->misses;
+ return NULL;
+}
+
+int drmHashLookup(void *t, unsigned long key, void **value)
+{
+ HashTablePtr table = (HashTablePtr)t;
+ HashBucketPtr bucket;
+
+ if (!table || table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+ bucket = HashFind(table, key, NULL);
+ if (!bucket) return 1; /* Not found */
+ *value = bucket->value;
+ return 0; /* Found */
+}
+
+int drmHashInsert(void *t, unsigned long key, void *value)
+{
+ HashTablePtr table = (HashTablePtr)t;
+ HashBucketPtr bucket;
+ unsigned long hash;
+
+ if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+ if (HashFind(table, key, &hash)) return 1; /* Already in table */
+
+ bucket = HASH_ALLOC(sizeof(*bucket));
+ if (!bucket) return -1; /* Error */
+ bucket->key = key;
+ bucket->value = value;
+ bucket->next = table->buckets[hash];
+ table->buckets[hash] = bucket;
+#if HASH_DEBUG
+ printf("Inserted %d at %d/%p\n", key, hash, bucket);
+#endif
+ return 0; /* Added to table */
+}
+
+int drmHashDelete(void *t, unsigned long key)
+{
+ HashTablePtr table = (HashTablePtr)t;
+ unsigned long hash;
+ HashBucketPtr bucket;
+
+ if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+ bucket = HashFind(table, key, &hash);
+
+ if (!bucket) return 1; /* Not found */
+
+ table->buckets[hash] = bucket->next;
+ HASH_FREE(bucket);
+ return 0;
+}
+
+int drmHashNext(void *t, unsigned long *key, void **value)
+{
+ HashTablePtr table = (HashTablePtr)t;
+
+ for (; table->p0 < HASH_SIZE;
+ ++table->p0, table->p1 = table->buckets[table->p0]) {
+ if (table->p1) {
+ *key = table->p1->key;
+ *value = table->p1->value;
+ table->p1 = table->p1->next;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int drmHashFirst(void *t, unsigned long *key, void **value)
+{
+ HashTablePtr table = (HashTablePtr)t;
+
+ if (table->magic != HASH_MAGIC) return -1; /* Bad magic */
+
+ table->p0 = 0;
+ table->p1 = table->buckets[0];
+ return drmHashNext(table, key, value);
+}
+
+#if HASH_MAIN
+#define DIST_LIMIT 10
+static int dist[DIST_LIMIT];
+
+static void clear_dist(void) {
+ int i;
+
+ for (i = 0; i < DIST_LIMIT; i++) dist[i] = 0;
+}
+
+static int count_entries(HashBucketPtr bucket)
+{
+ int count = 0;
+
+ for (; bucket; bucket = bucket->next) ++count;
+ return count;
+}
+
+static void update_dist(int count)
+{
+ if (count >= DIST_LIMIT) ++dist[DIST_LIMIT-1];
+ else ++dist[count];
+}
+
+static void compute_dist(HashTablePtr table)
+{
+ int i;
+ HashBucketPtr bucket;
+
+ printf("Entries = %ld, hits = %ld, partials = %ld, misses = %ld\n",
+ table->entries, table->hits, table->partials, table->misses);
+ clear_dist();
+ for (i = 0; i < HASH_SIZE; i++) {
+ bucket = table->buckets[i];
+ update_dist(count_entries(bucket));
+ }
+ for (i = 0; i < DIST_LIMIT; i++) {
+ if (i != DIST_LIMIT-1) printf("%5d %10d\n", i, dist[i]);
+ else printf("other %10d\n", dist[i]);
+ }
+}
+
+static void check_table(HashTablePtr table,
+ unsigned long key, unsigned long value)
+{
+ unsigned long retval = 0;
+ int retcode = drmHashLookup(table, key, &retval);
+
+ switch (retcode) {
+ case -1:
+ printf("Bad magic = 0x%08lx:"
+ " key = %lu, expected = %lu, returned = %lu\n",
+ table->magic, key, value, retval);
+ break;
+ case 1:
+ printf("Not found: key = %lu, expected = %lu returned = %lu\n",
+ key, value, retval);
+ break;
+ case 0:
+ if (value != retval)
+ printf("Bad value: key = %lu, expected = %lu, returned = %lu\n",
+ key, value, retval);
+ break;
+ default:
+ printf("Bad retcode = %d: key = %lu, expected = %lu, returned = %lu\n",
+ retcode, key, value, retval);
+ break;
+ }
+}
+
+int main(void)
+{
+ HashTablePtr table;
+ int i;
+
+ printf("\n***** 256 consecutive integers ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 256; i++) drmHashInsert(table, i, i);
+ for (i = 0; i < 256; i++) check_table(table, i, i);
+ for (i = 256; i >= 0; i--) check_table(table, i, i);
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 consecutive integers ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 1024; i++) drmHashInsert(table, i, i);
+ for (i = 0; i < 1024; i++) check_table(table, i, i);
+ for (i = 1024; i >= 0; i--) check_table(table, i, i);
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 consecutive page addresses (4k pages) ****\n");
+ table = drmHashCreate();
+ for (i = 0; i < 1024; i++) drmHashInsert(table, i*4096, i);
+ for (i = 0; i < 1024; i++) check_table(table, i*4096, i);
+ for (i = 1024; i >= 0; i--) check_table(table, i*4096, i);
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 1024 random integers ****\n");
+ table = drmHashCreate();
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++) drmHashInsert(table, random(), i);
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++) check_table(table, random(), i);
+ srandom(0xbeefbeef);
+ for (i = 0; i < 1024; i++) check_table(table, random(), i);
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ printf("\n***** 5000 random integers ****\n");
+ table = drmHashCreate();
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++) drmHashInsert(table, random(), i);
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++) check_table(table, random(), i);
+ srandom(0xbeefbeef);
+ for (i = 0; i < 5000; i++) check_table(table, random(), i);
+ compute_dist(table);
+ drmHashDestroy(table);
+
+ return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmRandom.c b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c
new file mode 100644
index 00000000000..cca831d7517
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmRandom.c
@@ -0,0 +1,217 @@
+/* xf86drmRandom.c -- "Minimal Standard" PRNG Implementation
+ * Created: Mon Apr 19 08:28:13 1999 by [email protected]
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors: Rickard E. (Rik) Faith <[email protected]>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRandom.c,v 1.4 2000/06/17 00:03:34 martin Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a simple, straightforward implementation of the Park
+ * & Miller "Minimal Standard" PRNG [PM88, PMS93], which is a Lehmer
+ * multiplicative linear congruential generator (MLCG) with a period of
+ * 2^31-1.
+ *
+ * This implementation is intended to provide a reliable, portable PRNG
+ * that is suitable for testing a hash table implementation and for
+ * implementing skip lists.
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * If initial seeds are not selected randomly, two instances of the PRNG
+ * can be correlated. [Knuth81, pp. 32-33] describes a shuffling technique
+ * that can eliminate this problem.
+ *
+ * If PRNGs are used for simulation, the period of the current
+ * implementation may be too short. [LE88] discusses methods of combining
+ * MLCGs to produce much longer periods, and suggests some alternative
+ * values for A and M. [LE90 and Sch92] also provide information on
+ * long-period PRNGs.
+ *
+ * REFERENCES
+ *
+ * [Knuth81] Donald E. Knuth. The Art of Computer Programming. Volume 2:
+ * Seminumerical Algorithms. Reading, Massachusetts: Addison-Wesley, 1981.
+ *
+ * [LE88] Pierre L'Ecuyer. "Efficient and Portable Combined Random Number
+ * Generators". CACM 31(6), June 1988, pp. 742-774.
+ *
+ * [LE90] Pierre L'Ecuyer. "Random Numbers for Simulation". CACM 33(10,
+ * October 1990, pp. 85-97.
+ *
+ * [PM88] Stephen K. Park and Keith W. Miller. "Random Number Generators:
+ * Good Ones are Hard to Find". CACM 31(10), October 1988, pp. 1192-1201.
+ *
+ * [Sch92] Bruce Schneier. "Pseudo-Ransom Sequence Generator for 32-Bit
+ * CPUs". Dr. Dobb's Journal 17(2), February 1992, pp. 34, 37-38, 40.
+ *
+ * [PMS93] Stephen K. Park, Keith W. Miller, and Paul K. Stockmeyer. In
+ * "Technical Correspondence: Remarks on Choosing and Implementing Random
+ * Number Generators". CACM 36(7), July 1993, pp. 105-110.
+ *
+ */
+
+#define RANDOM_MAIN 0
+
+#if RANDOM_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+# include "xf86.h"
+# include "xf86_ansic.h"
+# else
+# include <stdio.h>
+# include <stdlib.h>
+# endif
+#endif
+
+#define RANDOM_MAGIC 0xfeedbeef
+#define RANDOM_DEBUG 0
+
+#if RANDOM_MAIN
+#define RANDOM_ALLOC malloc
+#define RANDOM_FREE free
+#else
+#define RANDOM_ALLOC drmMalloc
+#define RANDOM_FREE drmFree
+#endif
+
+typedef struct RandomState {
+ unsigned long magic;
+ unsigned long a;
+ unsigned long m;
+ unsigned long q; /* m div a */
+ unsigned long r; /* m mod a */
+ unsigned long check;
+ long seed;
+} RandomState;
+
+#if RANDOM_MAIN
+extern void *drmRandomCreate(unsigned long seed);
+extern int drmRandomDestroy(void *state);
+extern unsigned long drmRandom(void *state);
+extern double drmRandomDouble(void *state);
+#endif
+
+void *drmRandomCreate(unsigned long seed)
+{
+ RandomState *state;
+
+ state = RANDOM_ALLOC(sizeof(*state));
+ if (!state) return NULL;
+ state->magic = RANDOM_MAGIC;
+#if 0
+ /* Park & Miller, October 1988 */
+ state->a = 16807;
+ state->m = 2147483647;
+ state->check = 1043618065; /* After 10000 iterations */
+#else
+ /* Park, Miller, and Stockmeyer, July 1993 */
+ state->a = 48271;
+ state->m = 2147483647;
+ state->check = 399268537; /* After 10000 iterations */
+#endif
+ state->q = state->m / state->a;
+ state->r = state->m % state->a;
+
+ state->seed = seed;
+ /* Check for illegal boundary conditions,
+ and choose closest legal value. */
+ if (state->seed <= 0) state->seed = 1;
+ if (state->seed >= state->m) state->seed = state->m - 1;
+
+ return state;
+}
+
+int drmRandomDestroy(void *state)
+{
+ RANDOM_FREE(state);
+ return 0;
+}
+
+unsigned long drmRandom(void *state)
+{
+ RandomState *s = (RandomState *)state;
+ long hi;
+ long lo;
+
+ hi = s->seed / s->q;
+ lo = s->seed % s->q;
+ s->seed = s->a * lo - s->r * hi;
+ if (s->seed <= 0) s->seed += s->m;
+
+ return s->seed;
+}
+
+double drmRandomDouble(void *state)
+{
+ RandomState *s = (RandomState *)state;
+
+ return (double)drmRandom(state)/(double)s->m;
+}
+
+#if RANDOM_MAIN
+static void check_period(long seed)
+{
+ unsigned long count = 0;
+ unsigned long initial;
+ void *state;
+
+ state = drmRandomCreate(seed);
+ initial = drmRandom(state);
+ ++count;
+ while (initial != drmRandom(state)) {
+ if (!++count) break;
+ }
+ printf("With seed of %10ld, period = %10lu (0x%08lx)\n",
+ seed, count, count);
+ drmRandomDestroy(state);
+}
+
+int main(void)
+{
+ RandomState *state;
+ int i;
+ unsigned long rand;
+
+ state = drmRandomCreate(1);
+ for (i = 0; i < 10000; i++) {
+ rand = drmRandom(state);
+ }
+ printf("After 10000 iterations: %lu (%lu expected): %s\n",
+ rand, state->check,
+ rand - state->check ? "*INCORRECT*" : "CORRECT");
+ drmRandomDestroy(state);
+
+ printf("Checking periods...\n");
+ check_period(1);
+ check_period(2);
+ check_period(31415926);
+
+ return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/dri_client/xf86drmSL.c b/src/mesa/drivers/dri/dri_client/xf86drmSL.c
new file mode 100644
index 00000000000..a9d64c920f0
--- /dev/null
+++ b/src/mesa/drivers/dri/dri_client/xf86drmSL.c
@@ -0,0 +1,488 @@
+/* xf86drmSL.c -- Skip list support
+ * Created: Mon May 10 09:28:13 1999 by [email protected]
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ * Authors: Rickard E. (Rik) Faith <[email protected]>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmSL.c,v 1.3 2000/06/17 00:03:34 martin Exp $
+ *
+ * DESCRIPTION
+ *
+ * This file contains a straightforward skip list implementation.n
+ *
+ * FUTURE ENHANCEMENTS
+ *
+ * REFERENCES
+ *
+ * [Pugh90] William Pugh. Skip Lists: A Probabilistic Alternative to
+ * Balanced Trees. CACM 33(6), June 1990, pp. 668-676.
+ *
+ */
+
+#define SL_MAIN 0
+
+#if SL_MAIN
+# include <stdio.h>
+# include <stdlib.h>
+# include <sys/time.h>
+#else
+# include "xf86drm.h"
+# ifdef XFree86LOADER
+# include "xf86.h"
+# include "xf86_ansic.h"
+# else
+# include <stdio.h>
+# include <stdlib.h>
+# endif
+#endif
+
+#define SL_LIST_MAGIC 0xfacade00LU
+#define SL_ENTRY_MAGIC 0x00fab1edLU
+#define SL_FREED_MAGIC 0xdecea5edLU
+#define SL_MAX_LEVEL 16
+#define SL_DEBUG 0
+#define SL_RANDOM_SEED 0xc01055a1LU
+
+#if SL_MAIN
+#define SL_ALLOC malloc
+#define SL_FREE free
+#define SL_RANDOM_DECL static int state = 0;
+#define SL_RANDOM_INIT(seed) if (!state) { srandom(seed); ++state; }
+#define SL_RANDOM random()
+#else
+#define SL_ALLOC drmMalloc
+#define SL_FREE drmFree
+#define SL_RANDOM_DECL static void *state = NULL
+#define SL_RANDOM_INIT(seed) if (!state) state = drmRandomCreate(seed)
+#define SL_RANDOM drmRandom(state)
+
+#endif
+
+typedef struct SLEntry {
+ unsigned long magic; /* SL_ENTRY_MAGIC */
+ unsigned long key;
+ void *value;
+ int levels;
+ struct SLEntry *forward[1]; /* variable sized array */
+} SLEntry, *SLEntryPtr;
+
+typedef struct SkipList {
+ unsigned long magic; /* SL_LIST_MAGIC */
+ int level;
+ int count;
+ SLEntryPtr head;
+ SLEntryPtr p0; /* Position for iteration */
+} SkipList, *SkipListPtr;
+
+#if SL_MAIN
+extern void *drmSLCreate(void);
+extern int drmSLDestroy(void *l);
+extern int drmSLLookup(void *l, unsigned long key, void **value);
+extern int drmSLInsert(void *l, unsigned long key, void *value);
+extern int drmSLDelete(void *l, unsigned long key);
+extern int drmSLNext(void *l, unsigned long *key, void **value);
+extern int drmSLFirst(void *l, unsigned long *key, void **value);
+extern void drmSLDump(void *l);
+extern int drmSLLookupNeighbors(void *l, unsigned long key,
+ unsigned long *prev_key, void **prev_value,
+ unsigned long *next_key, void **next_value);
+#endif
+
+static SLEntryPtr SLCreateEntry(int max_level, unsigned long key, void *value)
+{
+ SLEntryPtr entry;
+
+ if (max_level < 0 || max_level > SL_MAX_LEVEL) max_level = SL_MAX_LEVEL;
+
+ entry = SL_ALLOC(sizeof(*entry)
+ + (max_level + 1) * sizeof(entry->forward[0]));
+ if (!entry) return NULL;
+ entry->magic = SL_ENTRY_MAGIC;
+ entry->key = key;
+ entry->value = value;
+ entry->levels = max_level + 1;
+
+ return entry;
+}
+
+static int SLRandomLevel(void)
+{
+ int level = 1;
+ SL_RANDOM_DECL;
+
+ SL_RANDOM_INIT(SL_RANDOM_SEED);
+
+ while ((SL_RANDOM & 0x01) && level < SL_MAX_LEVEL) ++level;
+ return level;
+}
+
+void *drmSLCreate(void)
+{
+ SkipListPtr list;
+ int i;
+
+ list = SL_ALLOC(sizeof(*list));
+ if (!list) return NULL;
+ list->magic = SL_LIST_MAGIC;
+ list->level = 0;
+ list->head = SLCreateEntry(SL_MAX_LEVEL, 0, NULL);
+ list->count = 0;
+
+ for (i = 0; i <= SL_MAX_LEVEL; i++) list->head->forward[i] = NULL;
+
+ return list;
+}
+
+int drmSLDestroy(void *l)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr entry;
+ SLEntryPtr next;
+
+ if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+ for (entry = list->head; entry; entry = next) {
+ if (entry->magic != SL_ENTRY_MAGIC) return -1; /* Bad magic */
+ next = entry->forward[0];
+ entry->magic = SL_FREED_MAGIC;
+ SL_FREE(entry);
+ }
+
+ list->magic = SL_FREED_MAGIC;
+ SL_FREE(list);
+ return 0;
+}
+
+static SLEntryPtr SLLocate(void *l, unsigned long key, SLEntryPtr *update)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr entry;
+ int i;
+
+ if (list->magic != SL_LIST_MAGIC) return NULL;
+
+ for (i = list->level, entry = list->head; i >= 0; i--) {
+ while (entry->forward[i] && entry->forward[i]->key < key)
+ entry = entry->forward[i];
+ update[i] = entry;
+ }
+
+ return entry->forward[0];
+}
+
+int drmSLInsert(void *l, unsigned long key, void *value)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr entry;
+ SLEntryPtr update[SL_MAX_LEVEL + 1];
+ int level;
+ int i;
+
+ if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+ entry = SLLocate(list, key, update);
+
+ if (entry && entry->key == key) return 1; /* Already in list */
+
+
+ level = SLRandomLevel();
+ if (level > list->level) {
+ level = ++list->level;
+ update[level] = list->head;
+ }
+
+ entry = SLCreateEntry(level, key, value);
+
+ /* Fix up forward pointers */
+ for (i = 0; i <= level; i++) {
+ entry->forward[i] = update[i]->forward[i];
+ update[i]->forward[i] = entry;
+ }
+
+ ++list->count;
+ return 0; /* Added to table */
+}
+
+int drmSLDelete(void *l, unsigned long key)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr update[SL_MAX_LEVEL + 1];
+ SLEntryPtr entry;
+ int i;
+
+ if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+ entry = SLLocate(list, key, update);
+
+ if (!entry || entry->key != key) return 1; /* Not found */
+
+ /* Fix up forward pointers */
+ for (i = 0; i <= list->level; i++) {
+ if (update[i]->forward[i] == entry)
+ update[i]->forward[i] = entry->forward[i];
+ }
+
+ entry->magic = SL_FREED_MAGIC;
+ SL_FREE(entry);
+
+ while (list->level && !list->head->forward[list->level]) --list->level;
+ --list->count;
+ return 0;
+}
+
+int drmSLLookup(void *l, unsigned long key, void **value)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr update[SL_MAX_LEVEL + 1];
+ SLEntryPtr entry;
+
+ entry = SLLocate(list, key, update);
+
+ if (entry && entry->key == key) {
+ *value = entry;
+ return 0;
+ }
+ *value = NULL;
+ return -1;
+}
+
+int drmSLLookupNeighbors(void *l, unsigned long key,
+ unsigned long *prev_key, void **prev_value,
+ unsigned long *next_key, void **next_value)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr update[SL_MAX_LEVEL + 1];
+ SLEntryPtr entry;
+ int retcode = 0;
+
+ entry = SLLocate(list, key, update);
+
+ *prev_key = *next_key = key;
+ *prev_value = *next_value = NULL;
+
+ if (update[0]) {
+ *prev_key = update[0]->key;
+ *prev_value = update[0]->value;
+ ++retcode;
+ if (update[0]->forward[0]) {
+ *next_key = update[0]->forward[0]->key;
+ *next_value = update[0]->forward[0]->value;
+ ++retcode;
+ }
+ }
+ return retcode;
+}
+
+int drmSLNext(void *l, unsigned long *key, void **value)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr entry;
+
+ if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+ entry = list->p0;
+
+ if (entry) {
+ list->p0 = entry->forward[0];
+ *key = entry->key;
+ *value = entry->value;
+ return 1;
+ }
+ list->p0 = NULL;
+ return 0;
+}
+
+int drmSLFirst(void *l, unsigned long *key, void **value)
+{
+ SkipListPtr list = (SkipListPtr)l;
+
+ if (list->magic != SL_LIST_MAGIC) return -1; /* Bad magic */
+
+ list->p0 = list->head->forward[0];
+ return drmSLNext(list, key, value);
+}
+
+/* Dump internal data structures for debugging. */
+void drmSLDump(void *l)
+{
+ SkipListPtr list = (SkipListPtr)l;
+ SLEntryPtr entry;
+ int i;
+
+ if (list->magic != SL_LIST_MAGIC) {
+ printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
+ list->magic, SL_LIST_MAGIC);
+ return;
+ }
+
+ printf("Level = %d, count = %d\n", list->level, list->count);
+ for (entry = list->head; entry; entry = entry->forward[0]) {
+ if (entry->magic != SL_ENTRY_MAGIC) {
+ printf("Bad magic: 0x%08lx (expected 0x%08lx)\n",
+ list->magic, SL_ENTRY_MAGIC);
+ }
+ printf("\nEntry %p <0x%08lx, %p> has %2d levels\n",
+ entry, entry->key, entry->value, entry->levels);
+ for (i = 0; i < entry->levels; i++) {
+ if (entry->forward[i]) {
+ printf(" %2d: %p <0x%08lx, %p>\n",
+ i,
+ entry->forward[i],
+ entry->forward[i]->key,
+ entry->forward[i]->value);
+ } else {
+ printf(" %2d: %p\n", i, entry->forward[i]);
+ }
+ }
+ }
+}
+
+#if SL_MAIN
+static void print(SkipListPtr list)
+{
+ unsigned long key;
+ void *value;
+
+ if (drmSLFirst(list, &key, &value)) {
+ do {
+ printf("key = %5lu, value = %p\n", key, value);
+ } while (drmSLNext(list, &key, &value));
+ }
+}
+
+static double do_time(int size, int iter)
+{
+ SkipListPtr list;
+ int i, j;
+ unsigned long keys[1000000];
+ unsigned long previous;
+ unsigned long key;
+ void *value;
+ struct timeval start, stop;
+ double usec;
+ SL_RANDOM_DECL;
+
+ SL_RANDOM_INIT(12345);
+
+ list = drmSLCreate();
+
+ for (i = 0; i < size; i++) {
+ keys[i] = SL_RANDOM;
+ drmSLInsert(list, keys[i], NULL);
+ }
+
+ previous = 0;
+ if (drmSLFirst(list, &key, &value)) {
+ do {
+ if (key <= previous) {
+ printf( "%lu !< %lu\n", previous, key);
+ }
+ previous = key;
+ } while (drmSLNext(list, &key, &value));
+ }
+
+ gettimeofday(&start, NULL);
+ for (j = 0; j < iter; j++) {
+ for (i = 0; i < size; i++) {
+ if (drmSLLookup(list, keys[i], &value))
+ printf("Error %lu %d\n", keys[i], i);
+ }
+ }
+ gettimeofday(&stop, NULL);
+
+ usec = (double)(stop.tv_sec * 1000000 + stop.tv_usec
+ - start.tv_sec * 1000000 - start.tv_usec) / (size * iter);
+
+ printf("%0.2f microseconds for list length %d\n", usec, size);
+
+ drmSLDestroy(list);
+
+ return usec;
+}
+
+static void print_neighbors(void *list, unsigned long key)
+{
+ unsigned long prev_key = 0;
+ unsigned long next_key = 0;
+ void *prev_value;
+ void *next_value;
+ int retval;
+
+ retval = drmSLLookupNeighbors(list, key,
+ &prev_key, &prev_value,
+ &next_key, &next_value);
+ printf("Neighbors of %5lu: %d %5lu %5lu\n",
+ key, retval, prev_key, next_key);
+}
+
+int main(void)
+{
+ SkipListPtr list;
+ double usec, usec2, usec3, usec4;
+
+ list = drmSLCreate();
+ printf( "list at %p\n", list);
+
+ print(list);
+ printf("\n==============================\n\n");
+
+ drmSLInsert(list, 123, NULL);
+ drmSLInsert(list, 213, NULL);
+ drmSLInsert(list, 50, NULL);
+ print(list);
+ printf("\n==============================\n\n");
+
+ print_neighbors(list, 0);
+ print_neighbors(list, 50);
+ print_neighbors(list, 51);
+ print_neighbors(list, 123);
+ print_neighbors(list, 200);
+ print_neighbors(list, 213);
+ print_neighbors(list, 256);
+ printf("\n==============================\n\n");
+
+ drmSLDelete(list, 50);
+ print(list);
+ printf("\n==============================\n\n");
+
+ drmSLDump(list);
+ drmSLDestroy(list);
+ printf("\n==============================\n\n");
+
+ usec = do_time(100, 10000);
+ usec2 = do_time(1000, 500);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 1000.0/100.0, usec2 / usec);
+
+ usec3 = do_time(10000, 50);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 10000.0/100.0, usec3 / usec);
+
+ usec4 = do_time(100000, 4);
+ printf("Table size increased by %0.2f, search time increased by %0.2f\n",
+ 100000.0/100.0, usec4 / usec);
+
+ return 0;
+}
+#endif
diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c
index d6a61d98e52..9c1b770fbd1 100644
--- a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c
+++ b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c
@@ -341,7 +341,8 @@ void ffbInitTnlModule(GLcontext *ctx)
ffb_init_norm_funcs();
ffb_init_vert_funcs();
- MEMSET(vfmt, 0, sizeof(GLvertexformat));
+ /* start by initializing to no-op functions */
+ _mesa_noop_vtxfmt_init(vfmt);
/* Handled fully in supported states: */
vfmt->ArrayElement = NULL; /* FIXME: ... */
@@ -389,18 +390,8 @@ void ffbInitTnlModule(GLcontext *ctx)
vfmt->Begin = ffb_Begin;
vfmt->End = ffb_End;
- vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
-
vfmt->DrawArrays = NULL;
vfmt->DrawElements = NULL;
- vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */
-
-
- /* Not active in supported states; just keep ctx->Current uptodate: */
- vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
- vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
- vfmt->Indexi = _mesa_noop_Indexi;
- vfmt->Indexiv = _mesa_noop_Indexiv;
/* Active but unsupported -- fallback if we receive these:
*
diff --git a/src/mesa/drivers/dri/i810/i810context.c b/src/mesa/drivers/dri/i810/i810context.c
index a622051eddf..23373ef73b1 100644
--- a/src/mesa/drivers/dri/i810/i810context.c
+++ b/src/mesa/drivers/dri/i810/i810context.c
@@ -133,6 +133,7 @@ const struct dri_extension card_extensions[] =
{ "GL_EXT_texture_edge_clamp", NULL },
{ "GL_EXT_texture_env_combine", NULL },
{ "GL_EXT_texture_lod_bias", NULL },
+ { "GL_EXT_texture_rectangle", NULL },
{ "GL_MESA_ycbcr_texture", NULL },
{ "GL_NV_blend_square", NULL },
{ "GL_SGIS_generate_mipmap", NULL },
diff --git a/src/mesa/drivers/dri/i810/i810state.c b/src/mesa/drivers/dri/i810/i810state.c
index a79c3a3e4df..680b818d286 100644
--- a/src/mesa/drivers/dri/i810/i810state.c
+++ b/src/mesa/drivers/dri/i810/i810state.c
@@ -597,6 +597,7 @@ static void i810Enable(GLcontext *ctx, GLenum cap, GLboolean state)
imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE;
break;
case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_NV:
I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
if (ctx->Texture.CurrentUnit == 0) {
imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE;
diff --git a/src/mesa/drivers/dri/i810/i810texstate.c b/src/mesa/drivers/dri/i810/i810texstate.c
index 5133ea44d4b..558aef9eee4 100644
--- a/src/mesa/drivers/dri/i810/i810texstate.c
+++ b/src/mesa/drivers/dri/i810/i810texstate.c
@@ -115,8 +115,6 @@ static void i810SetTexImages( i810ContextPtr imesa,
t->max_level = i-1;
t->dirty = I810_UPLOAD_TEX0 | I810_UPLOAD_TEX1;
t->Setup[I810_TEXREG_MI1] = (MI1_MAP_0 | textureFormat | log_pitch);
- t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 |
- (log2Height << 16) | log2Width);
t->Setup[I810_TEXREG_MLL] = (GFX_OP_MAP_LOD_LIMITS |
MLL_MAP_0 |
MLL_UPDATE_MAX_MIP |
@@ -537,6 +535,92 @@ i810UpdateTexEnvCombine( GLcontext *ctx, GLuint unit,
return GL_TRUE;
}
+static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit )
+{
+ i810ContextPtr imesa = I810_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData;
+
+ if (tObj->Image[0][tObj->BaseLevel]->Border > 0) {
+ return GL_FALSE;
+ }
+
+ /* Upload teximages (not pipelined)
+ */
+ if (t->base.dirty_images[0]) {
+ I810_FIREVERTICES(imesa);
+ i810SetTexImages( imesa, tObj );
+ if (!t->base.memBlock) {
+ return GL_FALSE;
+ }
+ }
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+ if (imesa->CurrentTexObj[unit] != t) {
+ I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit));
+ imesa->CurrentTexObj[unit] = t;
+ t->base.bound |= (1U << unit);
+
+ /* XXX: should be locked */
+ driUpdateTextureLRU( (driTextureObject *) t );
+ }
+
+ imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
+ return GL_TRUE;
+}
+
+static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit )
+{
+ i810ContextPtr imesa = I810_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData;
+ GLint Width, Height;
+
+ Width = tObj->Image[0][t->base.firstLevel]->Width - 1;
+ Height = tObj->Image[0][t->base.firstLevel]->Height - 1;
+
+ I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit));
+ t->Setup[I810_TEXREG_MCS] &= ~MCS_NORMALIZED_COORDS;
+ t->Setup[I810_TEXREG_MCS] |= MCS_UPDATE_NORMALIZED;
+ t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_EXACT |
+ (Height << MI2_HEIGHT_SHIFT) | Width);
+
+ return GL_TRUE;
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit )
+{
+ i810ContextPtr imesa = I810_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *tObj = texUnit->_Current;
+ i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData;
+ GLint log2Width, log2Height;
+
+
+ log2Width = tObj->Image[0][t->base.firstLevel]->WidthLog2;
+ log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
+
+ I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit));
+ t->Setup[I810_TEXREG_MCS] |= MCS_NORMALIZED_COORDS | MCS_UPDATE_NORMALIZED;
+ t->Setup[I810_TEXREG_MI2] = (MI2_DIMENSIONS_ARE_LOG2 |
+ (log2Height << MI2_HEIGHT_SHIFT) | log2Width);
+
+ return GL_TRUE;
+}
+
+static void disable_tex( GLcontext *ctx, GLuint unit )
+{
+ i810ContextPtr imesa = I810_CONTEXT(ctx);
+
+ imesa->CurrentTexObj[unit] = 0;
+ imesa->TexEnvImageFmt[unit] = 0;
+ imesa->dirty &= ~(I810_UPLOAD_TEX0<<unit);
+
+}
/**
* Update hardware state for a texture unit.
@@ -550,62 +634,32 @@ static void i810UpdateTexUnit( GLcontext *ctx, GLuint unit,
{
i810ContextPtr imesa = I810_CONTEXT(ctx);
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLboolean ret;
+
+ switch(texUnit->_ReallyEnabled) {
+ case TEXTURE_2D_BIT:
+ ret = enable_tex_common( ctx, unit);
+ ret &= enable_tex_2d(ctx, unit);
+ if (ret == GL_FALSE) {
+ FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
+ }
+ break;
+ case TEXTURE_RECT_BIT:
+ ret = enable_tex_common( ctx, unit);
+ ret &= enable_tex_rect(ctx, unit);
+ if (ret == GL_FALSE) {
+ FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
+ }
+ break;
+ case 0:
+ disable_tex(ctx, unit);
+ break;
+ }
- if ( (texUnit->_ReallyEnabled == TEXTURE_2D_BIT)
- || (texUnit->_ReallyEnabled == 0) ) {
- if (texUnit->_ReallyEnabled != 0) {
- struct gl_texture_object *tObj = texUnit->_Current;
- i810TextureObjectPtr t = (i810TextureObjectPtr)tObj->DriverData;
-
- if (tObj->Image[0][tObj->BaseLevel]->Border > 0) {
- FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
- return;
- }
-
-
- /* Upload teximages (not pipelined)
- */
- if (t->base.dirty_images[0]) {
- I810_FIREVERTICES(imesa);
- i810SetTexImages( imesa, tObj );
- if (!t->base.memBlock) {
- FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
- return;
- }
- }
-
-
- /* Update state if this is a different texture object to last
- * time.
- */
- if (imesa->CurrentTexObj[unit] != t) {
- I810_STATECHANGE(imesa, (I810_UPLOAD_TEX0<<unit));
- imesa->CurrentTexObj[unit] = t;
- t->base.bound |= (1U << unit);
-
- /* XXX: should be locked */
- driUpdateTextureLRU( (driTextureObject *) t );
- }
-
- /* Update texture environment if texture object image format or
- * texture environment state has changed.
- */
- imesa->TexEnvImageFmt[unit] = tObj->Image[0][tObj->BaseLevel]->_BaseFormat;
- }
- else {
- imesa->CurrentTexObj[unit] = 0;
- imesa->TexEnvImageFmt[unit] = 0;
- imesa->dirty &= ~(I810_UPLOAD_TEX0<<unit);
- }
-
- if (!i810UpdateTexEnvCombine( ctx, unit,
- next_color_stage, next_alpha_stage )) {
- FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
- }
- }
- else if (texUnit->_ReallyEnabled) {
- FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
+ if (!i810UpdateTexEnvCombine( ctx, unit,
+ next_color_stage, next_alpha_stage )) {
+ FALLBACK( imesa, I810_FALLBACK_TEXTURE, GL_TRUE );
}
return;
diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile
index 53349364d04..805abf75e08 100644
--- a/src/mesa/drivers/dri/i915/Makefile
+++ b/src/mesa/drivers/dri/i915/Makefile
@@ -4,6 +4,8 @@ include $(TOP)/configs/current
LIBNAME = i915_dri.so
+MINIGLX_SOURCES = server/intel_dri.c
+
DRIVER_SOURCES = \
i915_context.c \
i915_debug.c \
@@ -37,7 +39,6 @@ DRIVER_SOURCES = \
C_SOURCES = \
$(COMMON_SOURCES) \
- $(MINIGLX_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =
diff --git a/src/mesa/drivers/dri/i915/i830_context.c b/src/mesa/drivers/dri/i915/i830_context.c
index 7a251ac6e89..d16b153fac2 100644
--- a/src/mesa/drivers/dri/i915/i830_context.c
+++ b/src/mesa/drivers/dri/i915/i830_context.c
@@ -84,7 +84,7 @@ GLboolean i830CreateContext( const __GLcontextModes *mesaVis,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
- & intel->sarea->texAge,
+ (unsigned *) & intel->sarea->texAge,
& intel->swapped,
sizeof( struct i830_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h
index 5bdcc21c5ab..d5811e6c349 100644
--- a/src/mesa/drivers/dri/i915/i830_context.h
+++ b/src/mesa/drivers/dri/i915/i830_context.h
@@ -118,7 +118,7 @@ struct i830_context
{
struct intel_context intel;
- GLuint last_index;
+ DECLARE_RENDERINPUTS(last_index_bitset);
struct i830_hw_state meta, initial, state, *current;
};
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index e8913e8063c..9e71b111091 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -65,11 +65,13 @@ static void i830_render_start( intelContextPtr intel )
i830ContextPtr i830 = I830_CONTEXT(intel);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint v0 = _3DSTATE_VFT0_CMD;
GLuint v2 = _3DSTATE_VFT1_CMD;
GLuint mcsb1 = 0;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
/* Important:
*/
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
@@ -78,7 +80,7 @@ static void i830_render_start( intelContextPtr intel )
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VFT0_XYZW );
intel->coloroffset = 4;
}
@@ -87,36 +89,37 @@ static void i830_render_start( intelContextPtr intel )
intel->coloroffset = 3;
}
- if (index & _TNL_BIT_POINTSIZE) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, VFT0_POINT_WIDTH );
}
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VFT0_DIFFUSE );
intel->specoffset = 0;
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
- if (index & _TNL_BIT_COLOR1) {
- intel->specoffset = intel->coloroffset + 1;
- EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC );
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
+ intel->specoffset = intel->coloroffset + 1;
+ EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VFT0_SPEC );
}
- else
- EMIT_PAD( 3 );
-
- if (index & _TNL_BIT_FOG)
- EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
else
- EMIT_PAD( 1 );
+ EMIT_PAD( 3 );
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
+ EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VFT0_SPEC );
+ else
+ EMIT_PAD( 1 );
}
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
int i, count = 0;
for (i = 0; i < I830_TEX_UNITS; i++) {
- if (index & _TNL_BIT_TEX(i)) {
- GLuint sz = VB->TexCoordPtr[i]->size;
- GLuint emit;
- GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
- ~TEXCOORDTYPE_MASK);
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
+ GLuint sz = VB->TexCoordPtr[i]->size;
+ GLuint emit;
+ GLuint mcs = (i830->state.Tex[i][I830_TEXREG_MCS] &
+ ~TEXCOORDTYPE_MASK);
switch (sz) {
case 1:
@@ -162,7 +165,7 @@ static void i830_render_start( intelContextPtr intel )
if (v0 != i830->state.Ctx[I830_CTXREG_VF] ||
v2 != i830->state.Ctx[I830_CTXREG_VF2] ||
mcsb1 != i830->state.Ctx[I830_CTXREG_MCSB1] ||
- index != i830->last_index) {
+ !RENDERINPUTS_EQUAL( index_bitset, i830->last_index_bitset )) {
I830_STATECHANGE( i830, I830_UPLOAD_CTX );
@@ -180,7 +183,7 @@ static void i830_render_start( intelContextPtr intel )
i830->state.Ctx[I830_CTXREG_VF] = v0;
i830->state.Ctx[I830_CTXREG_VF2] = v2;
i830->state.Ctx[I830_CTXREG_MCSB1] = mcsb1;
- i830->last_index = index;
+ RENDERINPUTS_COPY( i830->last_index_bitset, index_bitset );
assert(i830_check_vertex_size( intel, intel->vertex_size ));
}
diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c
index b5c3f58d458..783bbc2ab89 100644
--- a/src/mesa/drivers/dri/i915/i915_context.c
+++ b/src/mesa/drivers/dri/i915/i915_context.c
@@ -127,7 +127,7 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis,
12,
I830_NR_TEX_REGIONS,
intel->sarea->texList,
- & intel->sarea->texAge,
+ (unsigned *) & intel->sarea->texAge,
& intel->swapped,
sizeof( struct i915_texture_object ),
(destroy_texture_object_t *)intelDestroyTexObj );
diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h
index 26b8c69be9e..a088c087b65 100644
--- a/src/mesa/drivers/dri/i915/i915_context.h
+++ b/src/mesa/drivers/dri/i915/i915_context.h
@@ -311,6 +311,7 @@ extern void i915_print_ureg( const char *msg, GLuint ureg );
*/
extern void i915InitStateFunctions( struct dd_function_table *functions );
extern void i915InitState( i915ContextPtr i915 );
+extern void i915_update_fog(GLcontext *ctxx);
/*======================================================================
diff --git a/src/mesa/drivers/dri/i915/i915_texprog.c b/src/mesa/drivers/dri/i915/i915_texprog.c
index 74ece96f8b7..4fbce34ba21 100644
--- a/src/mesa/drivers/dri/i915/i915_texprog.c
+++ b/src/mesa/drivers/dri/i915/i915_texprog.c
@@ -576,11 +576,13 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
GLcontext *ctx = &intel->ctx;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
int i, offset;
GLuint s4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_VFMT_MASK;
GLuint s2 = S2_TEXCOORD_NONE;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
/* Important:
*/
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
@@ -591,9 +593,9 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
if (i915->vertex_fog == I915_FOG_PIXEL) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
- index &= ~_TNL_BIT_FOG;
+ RENDERINPUTS_CLEAR( index_bitset, _TNL_ATTRIB_FOG );
}
- else if (index & _TNL_BITS_TEX_ANY) {
+ else if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, S4_VFMT_XYZW, 16 );
}
else {
@@ -601,29 +603,30 @@ void i915ValidateTextureProgram( i915ContextPtr i915 )
}
/* How undefined is undefined? */
- if (index & _TNL_BIT_POINTSIZE) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_POINTSIZE )) {
EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, S4_VFMT_POINT_WIDTH, 4 );
}
intel->coloroffset = offset / 4;
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, S4_VFMT_COLOR, 4 );
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
intel->specoffset = offset / 4;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, S4_VFMT_SPEC_FOG, 3 );
} else
EMIT_PAD( 3 );
- if (index & _TNL_BIT_FOG)
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, S4_VFMT_SPEC_FOG, 1 );
else
EMIT_PAD( 1 );
}
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
for (i = 0; i < 8; i++) {
- if (index & _TNL_BIT_TEX(i)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
int sz = VB->TexCoordPtr[i]->size;
s2 &= ~S2_TEXCOORD_FMT(i, S2_TEXCOORD_FMT0_MASK);
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index 87eddfecdef..3b639e71443 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -456,7 +456,7 @@ static void i915SetTexImages( i915ContextPtr i915,
textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
break;
- case MESA_FORMAT_DEPTH_COMPONENT16:
+ case MESA_FORMAT_Z16:
t->intel.texelBytes = 2;
textureFormat = (MAPSURF_16BIT | MT_16BIT_L16);
break;
@@ -483,7 +483,7 @@ static void i915SetTexImages( i915ContextPtr i915,
break;
#if 0
- case MESA_FORMAT_DEPTH_COMPONENT_X8Z24:
+ case MESA_FORMAT_Z24_S8:
t->intel.texelBytes = 4;
textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824);
break;
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.c b/src/mesa/drivers/dri/i915/intel_batchbuffer.c
index 5979e236bcd..06312372776 100644
--- a/src/mesa/drivers/dri/i915/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.c
@@ -216,7 +216,7 @@ void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
}
#if 1
- if (((int)intel->batch.ptr) & 0x4) {
+ if (((unsigned long)intel->batch.ptr) & 0x4) {
BEGIN_BATCH(1);
OUT_BATCH(0);
ADVANCE_BATCH();
@@ -762,11 +762,6 @@ void intelInitBatchBuffer( GLcontext *ctx )
break;
}
- /* KW: temporary - this make crashes & lockups more frequent, so
- * leave in until they are solved.
- */
- intel->alloc.size = 8 * 1024;
-
intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
if (intel->alloc.ptr)
intel->alloc.offset =
diff --git a/src/mesa/drivers/dri/i915/intel_batchbuffer.h b/src/mesa/drivers/dri/i915/intel_batchbuffer.h
index b0aed89af55..577d07137ff 100644
--- a/src/mesa/drivers/dri/i915/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/i915/intel_batchbuffer.h
@@ -43,8 +43,9 @@ extern int VERBOSE;
#define BEGIN_BATCH(n) \
do { \
if (VERBOSE) fprintf(stderr, \
- "BEGIN_BATCH(%d) in %s, %d dwords free\n", \
- (n), __FUNCTION__, intel->batch.space/4); \
+ "BEGIN_BATCH(%ld) in %s, %d dwords free\n", \
+ ((unsigned long)n), __FUNCTION__, \
+ intel->batch.space/4); \
if (intel->batch.space < (n)*4) \
intelFlushBatch(intel, GL_TRUE); \
if (intel->batch.space == intel->batch.size) intel->batch.func = __FUNCTION__; \
diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h
index 2f362f9c2fb..19213b7bc55 100644
--- a/src/mesa/drivers/dri/i915/intel_context.h
+++ b/src/mesa/drivers/dri/i915/intel_context.h
@@ -207,7 +207,7 @@ struct intel_context
GLenum render_primitive;
GLenum reduced_primitive;
GLuint vertex_size;
- char *verts; /* points to tnl->clipspace.vertex_buf */
+ unsigned char *verts; /* points to tnl->clipspace.vertex_buf */
/* Fallback rasterization functions
diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c
index 82ad14ca114..d8530367664 100644
--- a/src/mesa/drivers/dri/i915/intel_ioctl.c
+++ b/src/mesa/drivers/dri/i915/intel_ioctl.c
@@ -140,7 +140,7 @@ void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock )
fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf);
intel->batch.start_offset = intel->alloc.offset + buf * half;
- intel->batch.ptr = (char *)intel->alloc.ptr + buf * half;
+ intel->batch.ptr = (unsigned char *)intel->alloc.ptr + buf * half;
intel->batch.size = half - 8;
intel->batch.space = half - 8;
assert(intel->batch.space >= 0);
@@ -418,7 +418,7 @@ void intelClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
if (!intel->hw_stencil) {
swrast_mask |= BUFFER_BIT_STENCIL;
}
- else if (ctx->Stencil.WriteMask[0] != 0xff) {
+ else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
tri_mask |= BUFFER_BIT_STENCIL;
}
else {
diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c
index aaafe84a6a0..2af38541d9c 100644
--- a/src/mesa/drivers/dri/i915/intel_pixel.c
+++ b/src/mesa/drivers/dri/i915/intel_pixel.c
@@ -157,13 +157,15 @@ intersect_region(const drm_clip_rect_t *box,
if (by < y) bh -= y - by, by = y;
if (bx + bw > x + width) bw = x + width - bx;
if (by + bh > y + height) bh = y + height - by;
- if (bw <= 0) return GL_FALSE;
- if (bh <= 0) return GL_FALSE;
*xOut = bx;
*yOut = by;
*wOut = bw;
*hOut = bh;
+
+ if (bw <= 0) return GL_FALSE;
+ if (bh <= 0) return GL_FALSE;
+
return GL_TRUE;
}
@@ -423,6 +425,8 @@ intelTryDrawPixels( GLcontext *ctx,
}
else
return GL_FALSE;
+
+ return GL_FALSE;
}
static void
diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c
index c8649d8243a..a87de17304f 100644
--- a/src/mesa/drivers/dri/i915/intel_screen.c
+++ b/src/mesa/drivers/dri/i915/intel_screen.c
@@ -666,7 +666,7 @@ void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIsc
*driver_modes = intelFillInModes( dri_priv->cpp * 8,
(dri_priv->cpp == 2) ? 16 : 24,
(dri_priv->cpp == 2) ? 0 : 8,
- (dri_priv->backOffset != dri_priv->depthOffset) );
+ 1 );
/* Calling driInitExtensions here, with a NULL context pointer, does not actually
* enable the extensions. It just makes sure that all the dispatch offsets for all
diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c
index 4bd7f92db0a..6012d3e7999 100644
--- a/src/mesa/drivers/dri/i915/intel_tex.c
+++ b/src/mesa/drivers/dri/i915/intel_tex.c
@@ -572,7 +572,7 @@ intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
case GL_DEPTH_COMPONENT16:
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32:
- return &_mesa_texformat_depth_component16;
+ return &_mesa_texformat_z16;
default:
fprintf(stderr, "unexpected texture format %s in %s\n",
@@ -787,7 +787,8 @@ int intelUploadTexImages( intelContextPtr intel,
}
/* Set the base offset of the texture image */
- t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs;
+ t->BufAddr = (GLubyte *) (intel->intelScreen->tex.map +
+ t->base.memBlock->ofs);
t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs;
t->dirty = ~0;
}
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
index cef6db7a195..e1a53212a51 100644
--- a/src/mesa/drivers/dri/i915/intel_tris.c
+++ b/src/mesa/drivers/dri/i915/intel_tris.c
@@ -642,7 +642,7 @@ void intelChooseRenderState(GLcontext *ctx)
TNLcontext *tnl = TNL_CONTEXT(ctx);
intelContextPtr intel = INTEL_CONTEXT(ctx);
GLuint flags = ctx->_TriangleCaps;
- struct fragment_program *fprog = ctx->FragmentProgram._Current;
+ const struct fragment_program *fprog = ctx->FragmentProgram._Current;
GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
GLuint index = 0;
diff --git a/src/mesa/drivers/dri/i915/server/intel.h b/src/mesa/drivers/dri/i915/server/intel.h
index 606db974b1c..d7858a20c8d 100644
--- a/src/mesa/drivers/dri/i915/server/intel.h
+++ b/src/mesa/drivers/dri/i915/server/intel.h
@@ -137,11 +137,6 @@ typedef struct {
int space;
} I830RingBuffer;
-typedef struct {
- unsigned int Fence[8];
-} I830RegRec, *I830RegPtr;
-
-
typedef struct _I830Rec {
unsigned char *MMIOBase;
unsigned char *FbBase;
@@ -194,6 +189,7 @@ typedef struct _I830Rec {
int GttBound;
drm_handle_t ring_map;
+ unsigned int Fence[8];
} I830Rec;
@@ -271,6 +267,44 @@ typedef struct _I830Rec {
#define RING_INVALID 0x00000000
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_PITCH_64 0x00000060
+#define FENCE_VALID 0x00000001
+
#include <mmio.h>
# define MMIO_IN8(base, offset) \
diff --git a/src/mesa/drivers/dri/i915/server/intel_dri.c b/src/mesa/drivers/dri/i915/server/intel_dri.c
index 2fd4a13052f..169fdbece30 100644
--- a/src/mesa/drivers/dri/i915/server/intel_dri.c
+++ b/src/mesa/drivers/dri/i915/server/intel_dri.c
@@ -46,10 +46,250 @@
#include "pciaccess.h"
static size_t drm_page_size;
+static int nextTile = 0;
#define xf86DrvMsg(...) do {} while(0)
+static const int pitches[] = {
+ 128 * 8,
+ 128 * 16,
+ 128 * 32,
+ 128 * 64,
+ 0
+};
+
static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+ unsigned long i;
+
+ for (i = KB(512); i < size; i <<= 1)
+ ;
+
+ if (i > MB(64))
+ i = MB(64);
+
+ return i;
+}
+
+static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+ unsigned char *MMIO = ctx->MMIOAddress;
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, pI830->Fence[i]);
+ // if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]);
+ }
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+static void
+SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
+ int nr, unsigned int start, unsigned int pitch,
+ unsigned int size)
+{
+ unsigned int val;
+ unsigned int fence_mask = 0;
+ unsigned int fence_pitch;
+
+ if (nr < 0 || nr > 7) {
+ fprintf(stderr,
+ "SetFence: fence %d out of range\n",nr);
+ return;
+ }
+
+ pI830->Fence[nr] = 0;
+
+ if (IS_I9XX(pI830))
+ fence_mask = ~I915G_FENCE_START_MASK;
+ else
+ fence_mask = ~I830_FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not %s aligned\n",
+ nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+ return;
+ }
+
+ if (start % size) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+ nr, start, size / 1024);
+ return;
+ }
+
+ if (pitch & 127) {
+ fprintf(stderr,
+ "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+ nr, pitch);
+ return;
+ }
+
+ val = (start | FENCE_X_MAJOR | FENCE_VALID);
+
+ if (IS_I9XX(pI830)) {
+ switch (size) {
+ case MB(1):
+ val |= I915G_FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= I915G_FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= I915G_FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= I915G_FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= I915G_FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= I915G_FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= I915G_FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ } else {
+ switch (size) {
+ case KB(512):
+ val |= FENCE_SIZE_512K;
+ break;
+ case MB(1):
+ val |= FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ }
+
+ if (IS_I9XX(pI830))
+ fence_pitch = pitch / 512;
+ else
+ fence_pitch = pitch / 128;
+
+ switch (fence_pitch) {
+ case 1:
+ val |= FENCE_PITCH_1;
+ break;
+ case 2:
+ val |= FENCE_PITCH_2;
+ break;
+ case 4:
+ val |= FENCE_PITCH_4;
+ break;
+ case 8:
+ val |= FENCE_PITCH_8;
+ break;
+ case 16:
+ val |= FENCE_PITCH_16;
+ break;
+ case 32:
+ val |= FENCE_PITCH_32;
+ break;
+ case 64:
+ val |= FENCE_PITCH_64;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+ return;
+ }
+
+ pI830->Fence[nr] = val;
+}
+
+static Bool
+MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
+{
+ int pitch, ntiles, i;
+
+ pitch = pMem->Pitch * ctx->cpp;
+ /*
+ * Simply try to break the region up into at most four pieces of size
+ * equal to the alignment.
+ */
+ ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+ if (ntiles >= 4) {
+ return FALSE;
+ }
+
+ for (i = 0; i < ntiles; i++, nextTile++) {
+ SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
+ pitch, pMem->Alignment);
+ }
+ return TRUE;
+}
+
+static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+
+ /* Clear out */
+ for (i = 0; i < 8; i++)
+ pI830->Fence[i] = 0;
+
+ nextTile = 0;
+
+ if (pI830->BackBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the back buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the back buffer.\n");
+ pI830->allowPageFlip = FALSE;
+ }
+ }
+
+ if (pI830->DepthBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the depth buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the depth buffer.\n");
+ }
+ }
+
+ return;
+}
+
static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
{
struct pci_device host_bridge;
@@ -139,6 +379,43 @@ static int AgpInit(const DRIDriverContext *ctx, I830Rec *info)
return 1;
}
+/*
+ * Allocate memory from the given pool. Grow the pool if needed and if
+ * possible.
+ */
+static unsigned long
+AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830,
+ I830MemRange *result, I830MemPool *pool,
+ long size, unsigned long alignment, int flags)
+{
+ long needed, start, end;
+
+ if (!result || !pool || !size)
+ return 0;
+
+ /* Calculate how much space is needed. */
+ if (alignment <= GTT_PAGE_SIZE)
+ needed = size;
+ else {
+ start = ROUND_TO(pool->Free.Start, alignment);
+ end = ROUND_TO(start + size, alignment);
+ needed = end - pool->Free.Start;
+ }
+ if (needed > pool->Free.Size) {
+ return 0;
+ }
+
+ result->Start = ROUND_TO(pool->Free.Start, alignment);
+ pool->Free.Start += needed;
+ result->End = pool->Free.Start;
+
+ pool->Free.Size = pool->Free.End - pool->Free.Start;
+ result->Size = result->End - result->Start;
+ result->Pool = pool;
+ result->Alignment = alignment;
+ return needed;
+}
+
static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result)
{
unsigned long start, end;
@@ -166,7 +443,7 @@ static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, l
pI830->MemoryAperture.Start = newApStart;
pI830->MemoryAperture.End = newApEnd;
pI830->MemoryAperture.Size = newApEnd - newApStart;
- pI830->FreeMemory -= size;
+ // pI830->FreeMemory -= size;
result->Start = start;
result->End = start + size;
result->Size = size;
@@ -177,6 +454,34 @@ static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, l
return size;
}
+unsigned long
+I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *result, I830MemPool *pool, long size, unsigned long alignment, int flags)
+{
+ int ret;
+
+ if (!result)
+ return 0;
+
+ /* Make sure these are initialised. */
+ result->Size = 0;
+ result->Key = -1;
+
+ if (!size) {
+ return 0;
+ }
+
+ if (pool->Free.Size < size)
+ return AllocFromAGP(ctx, pI830, size, alignment, result);
+ else
+ {
+ ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
+
+ if (ret==0)
+ return AllocFromAGP(ctx, pI830, size, alignment, result);
+ return ret;
+ }
+}
+
static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
{
if (!mem)
@@ -185,7 +490,7 @@ static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
if (mem->Key == -1)
return TRUE;
- return drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
+ return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
}
/* simple memory allocation routines needed */
@@ -207,7 +512,7 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
size = PRIMARY_RINGBUFFER_SIZE;
- ret = AllocFromAGP(ctx, pI830, size, 0x1000, &pI830->LpRing->mem);
+ ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
if (ret != size)
{
@@ -230,8 +535,10 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
size = lineSize * lines;
size = ROUND_TO_PAGE(size);
- ret = AllocFromAGP(ctx, pI830, size, align, &pI830->FrontBuffer);
- if (ret != size)
+ align = GetBestTileAlignment(size);
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
{
fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
return FALSE;
@@ -241,8 +548,8 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
pI830->BackBuffer.Key = -1;
pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
- ret = AllocFromAGP(ctx, pI830, size, align, &pI830->BackBuffer);
- if (ret != size)
+ ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
{
fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
return FALSE;
@@ -252,8 +559,8 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
pI830->DepthBuffer.Key = -1;
pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
- ret = AllocFromAGP(ctx, pI830, size, align, &pI830->DepthBuffer);
- if (ret != size)
+ ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
{
fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
return FALSE;
@@ -263,10 +570,10 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
pI830->ContextMem.Key = -1;
size = KB(32);
- ret = AllocFromAGP(ctx, pI830, size, align, &pI830->ContextMem);
- if (ret != size)
+ ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
{
- fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
+ fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
return FALSE;
}
@@ -275,7 +582,7 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
size = 32768 * 1024;
ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
- if (ret != size)
+ if (ret < size)
{
fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
return FALSE;
@@ -287,17 +594,17 @@ I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
static Bool
I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
{
- if (BindAgpRange(ctx, &pI830->LpRing->mem))
+ if (!BindAgpRange(ctx, &pI830->LpRing->mem))
return FALSE;
- if (BindAgpRange(ctx, &pI830->FrontBuffer))
+ if (!BindAgpRange(ctx, &pI830->FrontBuffer))
return FALSE;
- if (BindAgpRange(ctx, &pI830->BackBuffer))
+ if (!BindAgpRange(ctx, &pI830->BackBuffer))
return FALSE;
- if (BindAgpRange(ctx, &pI830->DepthBuffer))
+ if (!BindAgpRange(ctx, &pI830->DepthBuffer))
return FALSE;
- if (BindAgpRange(ctx, &pI830->ContextMem))
+ if (!BindAgpRange(ctx, &pI830->ContextMem))
return FALSE;
- if (BindAgpRange(ctx, &pI830->TexMem))
+ if (!BindAgpRange(ctx, &pI830->TexMem))
return FALSE;
return TRUE;
@@ -313,7 +620,7 @@ I830CleanupDma(const DRIDriverContext *ctx)
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
&info, sizeof(drmI830Init))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Cleanup Failed\n");
+ fprintf(stderr, "I830 Dma Cleanup Failed\n");
return FALSE;
}
@@ -345,11 +652,11 @@ I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
info.pitch = ctx->shared.virtualWidth;
info.back_pitch = pI830->BackBuffer.Pitch;
info.depth_pitch = pI830->DepthBuffer.Pitch;
- info.cpp = pI830->cpp;
+ info.cpp = ctx->cpp;
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
&info, sizeof(drmI830Init))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830 Dma Initialization Failed\n");
return FALSE;
}
@@ -408,7 +715,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
pI830->LpRing->mem.Start) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830SetRingRegs: Ring buffer start (%lx) violates its "
"mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
}
@@ -418,7 +725,7 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
pI830->LpRing->mem.Size - 4096) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
"mask (%x)\n", pI830->LpRing->mem.Size - 4096,
I830_RING_NR_PAGES);
@@ -433,6 +740,8 @@ I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
if (pI830->LpRing->space < 0)
pI830->LpRing->space += pI830->LpRing->mem.Size;
+
+ SetFenceRegs(ctx, pI830);
/* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
hacky hacky */
@@ -450,7 +759,7 @@ I830SetParam(const DRIDriverContext *ctx, int param, int value)
sp.value = value;
if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 SetParam Failed\n");
+ fprintf(stderr, "I830 SetParam Failed\n");
return FALSE;
}
@@ -482,7 +791,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)(sarea->back_offset),
sarea->back_size, DRM_AGP, 0,
&sarea->back_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -493,7 +802,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)sarea->depth_offset,
sarea->depth_size, DRM_AGP, 0,
&sarea->depth_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -504,7 +813,7 @@ I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sar
(drm_handle_t)sarea->tex_offset,
sarea->tex_size, DRM_AGP, 0,
&sarea->tex_handle) < 0) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
return FALSE;
}
@@ -549,10 +858,10 @@ I830InitTextureHeap(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *s
if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT_HEAP,
&drmHeap, sizeof(drmHeap))) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] Failed to initialized agp heap manager\n");
} else {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ fprintf(stderr,
"[drm] Initialized kernel agp heap manager, %d\n",
sarea->tex_size);
@@ -597,18 +906,18 @@ I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
ctx->pciFunc);
if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ fprintf(stderr,
"[drm] failure adding irq handler\n");
pI830->irq = 0;
return FALSE;
}
else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ fprintf(stderr,
"[drm] dma control initialized, using IRQ %d\n",
- pI830DRI->irq);
+ pI830->irq);
}
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized\n");
+ fprintf(stderr, "[dri] visual configs initialized\n");
return TRUE;
}
@@ -663,7 +972,6 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
I830DRIPtr pI830DRI;
drmI830Sarea *pSAREAPriv;
int err;
-
drm_page_size = getpagesize();
@@ -675,7 +983,7 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
*/
ctx->shared.SAREASize = SAREA_MAX;
- /* Note that drmOpen will try to load the kernel module, if needed. */
+ /* Note that drmOpen will try to load the kernel module, if needed. */
ctx->drmFD = drmOpen("i915", NULL );
if (ctx->drmFD < 0) {
fprintf(stderr, "[drm] drmOpen failed\n");
@@ -757,6 +1065,11 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
pI830->MemoryAperture.End = KB(40000);
pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
+ pI830->StolenPool.Fixed = pI830->StolenMemory;
+ pI830->StolenPool.Total = pI830->StolenMemory;
+ pI830->StolenPool.Free = pI830->StolenPool.Total;
+ pI830->FreeMemory = pI830->StolenPool.Total.Size;
+
if (!AgpInit(ctx, pI830))
return FALSE;
@@ -810,6 +1123,8 @@ I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
if (err == FALSE)
return FALSE;
+ I830SetupMemoryTiling(ctx, pI830);
+
/* Quick hack to clear the front & back buffers. Could also use
* the clear ioctl to do this, but would need to setup hw state
* first.
@@ -873,6 +1188,7 @@ static int i830PostValidateMode( const DRIDriverContext *ctx )
static int i830InitFBDev( DRIDriverContext *ctx )
{
I830Rec *pI830 = calloc(1, sizeof(I830Rec));
+ int i;
{
int dummy = ctx->shared.virtualWidth;
@@ -885,6 +1201,15 @@ static int i830InitFBDev( DRIDriverContext *ctx )
}
ctx->shared.virtualWidth = dummy;
+ ctx->shared.Width = ctx->shared.virtualWidth;
+ }
+
+
+ for (i = 0; pitches[i] != 0; i++) {
+ if (pitches[i] >= ctx->shared.virtualWidth) {
+ ctx->shared.virtualWidth = pitches[i];
+ break;
+ }
}
ctx->driverPrivate = (void *)pI830;
diff --git a/src/mesa/drivers/dri/mga/README b/src/mesa/drivers/dri/mga/README
new file mode 100644
index 00000000000..a7133fa66f4
--- /dev/null
+++ b/src/mesa/drivers/dri/mga/README
@@ -0,0 +1,26 @@
+MGA DRI driver ported from XF86DRI to FBDRI
+by Denis Oliver Kropp <[email protected]>
+
+
+INFO
+
+This driver has been ported from the head branch of XFree86 to
+the embedded-1-branch of Mesa.
+
+
+STATUS
+
+Already working very well as far as I've tested it (16/32 bit).
+glxgears runs at 935 fps (G550 32MB AGP 4x, Athlon 1.33) vs 744 fps with XFree.
+Other demos (terrain, fire, etc.) have been successfully tested as well.
+
+
+TODO
+
+- mgaEngineShutdown
+- mgaEngineRestore
+- SGRAM detection
+- remove some unused bits from server/*
+- subset driver support
+- mgaWaitForVBlank
+- deinitialization (from MGADRICloseScreen) a la radeonDestroyScreen
diff --git a/src/mesa/drivers/dri/mga/mgaioctl.c b/src/mesa/drivers/dri/mga/mgaioctl.c
index df253d15934..6e653f8c73d 100644
--- a/src/mesa/drivers/dri/mga/mgaioctl.c
+++ b/src/mesa/drivers/dri/mga/mgaioctl.c
@@ -50,7 +50,7 @@
#include "vblank.h"
-int
+static int
mgaSetFence( mgaContextPtr mmesa, uint32_t * fence )
{
int ret = ENOSYS;
@@ -68,7 +68,7 @@ mgaSetFence( mgaContextPtr mmesa, uint32_t * fence )
}
-int
+static int
mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence )
{
int ret = ENOSYS;
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
index 75f618ad37a..2f30bd253bf 100644
--- a/src/mesa/drivers/dri/r128/r128_context.c
+++ b/src/mesa/drivers/dri/r128/r128_context.c
@@ -190,7 +190,7 @@ GLboolean r128CreateContext( const __GLcontextModes *glVisual,
rmesa->RenderIndex = -1; /* Impossible value */
rmesa->vert_buf = NULL;
rmesa->num_verts = 0;
- rmesa->tnl_state = ~0;
+ RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
/* Set the maximum texture size small enough that we can guarentee that
* all texture units can bind a maximal texture and have them both in
@@ -296,10 +296,6 @@ void r128DestroyContext( __DRIcontextPrivate *driContextPriv )
_ac_DestroyContext( rmesa->glCtx );
_swrast_DestroyContext( rmesa->glCtx );
- /* free the Mesa context */
- rmesa->glCtx->DriverCtx = NULL;
- _mesa_destroy_context(rmesa->glCtx);
-
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
@@ -314,6 +310,10 @@ void r128DestroyContext( __DRIcontextPrivate *driContextPriv )
assert( is_empty_list( & rmesa->swapped ) );
}
+ /* free the Mesa context */
+ rmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(rmesa->glCtx);
+
/* free the option cache */
driDestroyOptionCache (&rmesa->optionCache);
diff --git a/src/mesa/drivers/dri/r128/r128_context.h b/src/mesa/drivers/dri/r128/r128_context.h
index b3552ac7639..c51dd7fa58d 100644
--- a/src/mesa/drivers/dri/r128/r128_context.h
+++ b/src/mesa/drivers/dri/r128/r128_context.h
@@ -130,7 +130,7 @@ struct r128_context {
char *verts; /* points to tnl->clipspace.vertex_buf */
GLuint num_verts;
int coloroffset, specoffset;
- int tnl_state; /* tnl->render_inputs for this _tnl_install_attrs */
+ DECLARE_RENDERINPUTS(tnl_state_bitset); /* tnl->render_inputs for this _tnl_install_attrs */
GLuint NewGLState;
GLuint Fallback;
diff --git a/src/mesa/drivers/dri/r128/r128_lock.c b/src/mesa/drivers/dri/r128/r128_lock.c
index ef67bc6a43a..393dd1ed74c 100644
--- a/src/mesa/drivers/dri/r128/r128_lock.c
+++ b/src/mesa/drivers/dri/r128/r128_lock.c
@@ -89,7 +89,7 @@ void r128GetLock( r128ContextPtr rmesa, GLuint flags )
driUpdateFramebufferSize(rmesa->glCtx, dPriv);
rmesa->lastStamp = dPriv->lastStamp;
rmesa->new_state |= R128_NEW_CLIP;
- rmesa->tnl_state = ~0;
+ RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
}
rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS;
diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c
index e9149306d87..1b2c2a5284e 100644
--- a/src/mesa/drivers/dri/r128/r128_state.c
+++ b/src/mesa/drivers/dri/r128/r128_state.c
@@ -260,9 +260,9 @@ r128DDStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
GLint ref, GLuint mask )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
- GLuint refmask = ((ctx->Stencil.Ref[0] << 0) |
- (ctx->Stencil.ValueMask[0] << 16) |
- (ctx->Stencil.WriteMask[0] << 24));
+ GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) |
+ ((ctx->Stencil.ValueMask[0] & 0xff) << 16) |
+ ((ctx->Stencil.WriteMask[0] & 0xff) << 24));
GLuint z = rmesa->setup.z_sten_cntl_c;
z &= ~R128_STENCIL_TEST_MASK;
@@ -307,9 +307,9 @@ static void
r128DDStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
- GLuint refmask = ((ctx->Stencil.Ref[0] << 0) |
- (ctx->Stencil.ValueMask[0] << 16) |
- (ctx->Stencil.WriteMask[0] << 24));
+ GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << 0) |
+ ((ctx->Stencil.ValueMask[0] & 0xff) << 16) |
+ ((ctx->Stencil.WriteMask[0] & 0xff) << 24));
if ( rmesa->setup.sten_ref_mask_c != refmask ) {
rmesa->setup.sten_ref_mask_c = refmask;
diff --git a/src/mesa/drivers/dri/r128/r128_tris.c b/src/mesa/drivers/dri/r128/r128_tris.c
index 64f54682b6e..46315225165 100644
--- a/src/mesa/drivers/dri/r128/r128_tris.c
+++ b/src/mesa/drivers/dri/r128/r128_tris.c
@@ -564,11 +564,13 @@ static void r128RenderStart( GLcontext *ctx )
r128ContextPtr rmesa = R128_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint vc_frmt = 0;
GLboolean fallback_projtex = GL_FALSE;
GLuint offset = 0;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
/* Important: */
VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
rmesa->vertex_attr_count = 0;
@@ -577,7 +579,7 @@ static void r128RenderStart( GLcontext *ctx )
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
- if ( index & _TNL_BITS_TEX_ANY )
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ))
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, R128_CCE_VC_FRMT_RHW, 16 );
else
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 12 );
@@ -591,28 +593,29 @@ static void r128RenderStart( GLcontext *ctx )
R128_CCE_VC_FRMT_DIFFUSE_ARGB, 4 );
#endif
- if ( index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG) ) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
#if MESA_LITTLE_ENDIAN
- if ( index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR,
R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
} else
EMIT_PAD( 3 );
- if (index & _TNL_BIT_FOG)
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
1 );
else
EMIT_PAD( 1 );
#else
- if (index & _TNL_BIT_FOG)
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, R128_CCE_VC_FRMT_SPEC_FRGB,
1 );
else
EMIT_PAD( 1 );
- if ( index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
R128_CCE_VC_FRMT_SPEC_FRGB, 3 );
@@ -621,12 +624,12 @@ static void r128RenderStart( GLcontext *ctx )
#endif
}
- if ( index & _TNL_BIT_TEX(rmesa->tmu_source[0]) ) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[0]) )) {
if ( VB->TexCoordPtr[rmesa->tmu_source[0]]->size > 2 )
fallback_projtex = GL_TRUE;
EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, R128_CCE_VC_FRMT_S_T, 8 );
}
- if ( index & _TNL_BIT_TEX(rmesa->tmu_source[1]) ) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(rmesa->tmu_source[1]) )) {
if ( VB->TexCoordPtr[rmesa->tmu_source[1]]->size > 2 )
fallback_projtex = GL_TRUE;
EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, R128_CCE_VC_FRMT_S2_T2, 8 );
@@ -638,7 +641,7 @@ static void r128RenderStart( GLcontext *ctx )
/* Only need to change the vertex emit code if there has been a
* statechange to a TNL index.
*/
- if ( index != rmesa->tnl_state ) {
+ if (!RENDERINPUTS_EQUAL( index_bitset, rmesa->tnl_state_bitset )) {
FLUSH_BATCH( rmesa );
rmesa->dirty |= R128_UPLOAD_CONTEXT;
@@ -763,7 +766,7 @@ void r128InitTriFuncs( GLcontext *ctx )
_tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
(6 + 2 * ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
rmesa->verts = (char *)tnl->clipspace.vertex_buf;
- rmesa->tnl_state = -1;
+ RENDERINPUTS_ONES( rmesa->tnl_state_bitset );
rmesa->NewGLState |= _R128_NEW_RENDER_STATE;
}
diff --git a/src/mesa/drivers/dri/r200/Makefile b/src/mesa/drivers/dri/r200/Makefile
index 7d8a170a650..2084d52132e 100644
--- a/src/mesa/drivers/dri/r200/Makefile
+++ b/src/mesa/drivers/dri/r200/Makefile
@@ -38,7 +38,7 @@ C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
X86_SOURCES = r200_vtxtmp_x86.S
-DEFINES += -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200
+DRIVER_DEFINES = -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R200
SYMLINKS = \
server/radeon_egl.c \
diff --git a/src/mesa/drivers/dri/r200/r200_context.c b/src/mesa/drivers/dri/r200/r200_context.c
index e4d9e264bf9..aaaaa5a95bf 100644
--- a/src/mesa/drivers/dri/r200/r200_context.c
+++ b/src/mesa/drivers/dri/r200/r200_context.c
@@ -107,7 +107,7 @@ static const GLubyte *r200GetString( GLcontext *ctx, GLenum name )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
static char buffer[128];
unsigned offset;
- GLuint agp_mode = rmesa->r200Screen->IsPCI ? 0 :
+ GLuint agp_mode = (rmesa->r200Screen->card_type == RADEON_CARD_PCI)? 0 :
rmesa->r200Screen->AGPMode;
switch ( name ) {
@@ -590,10 +590,6 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
r200VtxfmtDestroy( rmesa->glCtx );
}
- /* free the Mesa context */
- rmesa->glCtx->DriverCtx = NULL;
- _mesa_destroy_context( rmesa->glCtx );
-
if (rmesa->state.scissor.pClipRects) {
FREE(rmesa->state.scissor.pClipRects);
rmesa->state.scissor.pClipRects = NULL;
@@ -613,6 +609,10 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
assert( is_empty_list( & rmesa->swapped ) );
}
+ /* free the Mesa context */
+ rmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context( rmesa->glCtx );
+
/* free the option cache */
driDestroyOptionCache (&rmesa->optionCache);
diff --git a/src/mesa/drivers/dri/r200/r200_context.h b/src/mesa/drivers/dri/r200/r200_context.h
index faf1b96a2b8..f6709d3d7fd 100644
--- a/src/mesa/drivers/dri/r200/r200_context.h
+++ b/src/mesa/drivers/dri/r200/r200_context.h
@@ -897,7 +897,7 @@ struct r200_context {
GLuint TclFallback;
GLuint Fallback;
GLuint NewGLState;
- GLuint tnl_index; /* index of bits for last tnl_install_attrs */
+ DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
/* Vertex buffers
*/
diff --git a/src/mesa/drivers/dri/r200/r200_state.c b/src/mesa/drivers/dri/r200/r200_state.c
index 43ae7b66780..6ffb48c1505 100644
--- a/src/mesa/drivers/dri/r200/r200_state.c
+++ b/src/mesa/drivers/dri/r200/r200_state.c
@@ -1452,8 +1452,8 @@ r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
GLint ref, GLuint mask )
{
r200ContextPtr rmesa = R200_CONTEXT(ctx);
- GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
- (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
+ GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
+ ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
R200_STATECHANGE( rmesa, ctx );
R200_STATECHANGE( rmesa, msk );
@@ -1500,7 +1500,7 @@ r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
R200_STATECHANGE( rmesa, msk );
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
- (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
+ ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
}
static void
@@ -1601,9 +1601,9 @@ static void r200ClearStencil( GLcontext *ctx, GLint s )
r200ContextPtr rmesa = R200_CONTEXT(ctx);
rmesa->state.stencil.clear =
- ((GLuint) ctx->Stencil.Clear |
+ ((GLuint) (ctx->Stencil.Clear & 0xff) |
(0xff << R200_STENCIL_MASK_SHIFT) |
- (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
+ ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
}
diff --git a/src/mesa/drivers/dri/r200/r200_swtcl.c b/src/mesa/drivers/dri/r200/r200_swtcl.c
index 7ab3f7cd032..aa78f382868 100644
--- a/src/mesa/drivers/dri/r200/r200_swtcl.c
+++ b/src/mesa/drivers/dri/r200/r200_swtcl.c
@@ -85,11 +85,12 @@ static void r200SetVertexFormat( GLcontext *ctx )
r200ContextPtr rmesa = R200_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
int fmt_0 = 0;
int fmt_1 = 0;
int offset = 0;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
/* Important:
*/
@@ -106,7 +107,8 @@ static void r200SetVertexFormat( GLcontext *ctx )
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
- if ( !rmesa->swtcl.needproj || (index & _TNL_BITS_TEX_ANY)) { /* need w coord for projected textures */
+ if ( !rmesa->swtcl.needproj ||
+ RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* need w coord for projected textures */
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
offset = 4;
}
@@ -124,10 +126,11 @@ static void r200SetVertexFormat( GLcontext *ctx )
offset += 1;
rmesa->swtcl.specoffset = 0;
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
#if MESA_LITTLE_ENDIAN
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->swtcl.specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
}
@@ -135,21 +138,21 @@ static void r200SetVertexFormat( GLcontext *ctx )
EMIT_PAD( 3 );
}
- if (index & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
}
else {
EMIT_PAD( 1 );
}
#else
- if (index & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
}
else {
EMIT_PAD( 1 );
}
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->swtcl.specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
}
@@ -159,11 +162,11 @@ static void r200SetVertexFormat( GLcontext *ctx )
#endif
}
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
int i;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (index & _TNL_BIT_TEX(i)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
GLuint sz = VB->TexCoordPtr[i]->size;
fmt_1 |= sz << (3 * i);
@@ -179,7 +182,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
}
- if ( rmesa->tnl_index != index ||
+ if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
(rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
(rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
R200_NEWPRIM(rmesa);
@@ -193,7 +196,7 @@ static void r200SetVertexFormat( GLcontext *ctx )
rmesa->swtcl.vertex_attr_count,
NULL, 0 );
rmesa->swtcl.vertex_size /= 4;
- rmesa->tnl_index = index;
+ RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
}
}
@@ -235,12 +238,12 @@ void r200ChooseVertexState( GLcontext *ctx )
/* HW perspective divide is a win, but tiny vertex formats are a
* bigger one.
*/
- if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0)
+ if (!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )
|| (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
rmesa->swtcl.needproj = GL_TRUE;
vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
vte &= ~R200_VTX_W0_FMT;
- if (tnl->render_inputs & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
vap &= ~R200_VAP_FORCE_W_TO_ONE;
}
else {
@@ -719,7 +722,7 @@ void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
*/
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
- rmesa->tnl_index = 0;
+ RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
r200ChooseVertexState( ctx );
r200ChooseRenderState( ctx );
}
diff --git a/src/mesa/drivers/dri/r200/r200_vtxfmt.c b/src/mesa/drivers/dri/r200/r200_vtxfmt.c
index f42a046c00d..673076d0605 100644
--- a/src/mesa/drivers/dri/r200/r200_vtxfmt.c
+++ b/src/mesa/drivers/dri/r200/r200_vtxfmt.c
@@ -1056,12 +1056,16 @@ static void r200VtxFmtFlushVertices( GLcontext *ctx, GLuint flags )
*/
+/**
+ * Called once during context creation.
+ */
void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
{
r200ContextPtr rmesa = R200_CONTEXT( ctx );
GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
- MEMSET( vfmt, 0, sizeof(GLvertexformat) );
+ /* start by initializing to no-op functions */
+ _mesa_noop_vtxfmt_init(vfmt);
/* Hook in chooser functions for codegen, etc:
*/
@@ -1071,7 +1075,6 @@ void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
*/
vfmt->Materialfv = r200_Materialfv;
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
- vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
vfmt->Begin = r200_Begin;
vfmt->End = r200_End;
@@ -1085,15 +1088,6 @@ void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
vfmt->DrawElements = r200_fallback_DrawElements;
vfmt->DrawRangeElements = r200_fallback_DrawRangeElements;
-
- /* Not active in supported states; just keep ctx->Current uptodate:
- */
- vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
- vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
- vfmt->Indexf = _mesa_noop_Indexf;
- vfmt->Indexfv = _mesa_noop_Indexfv;
-
-
/* Active but unsupported -- fallback if we receive these:
*/
vfmt->CallList = r200_fallback_CallList;
diff --git a/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S b/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S
index 57a35c657b8..5e33c7bdeea 100644
--- a/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S
+++ b/src/mesa/drivers/dri/r200/r200_vtxtmp_x86.S
@@ -493,3 +493,7 @@ GLOBL( _sse_MultiTexCoord2f_2 )
ret
GLOBL( _sse_MultiTexCoord2f_2_end )
#endif
+
+#if defined (__ELF__) && defined (__linux__)
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/mesa/drivers/dri/r300/Makefile b/src/mesa/drivers/dri/r300/Makefile
index 3158ac8412b..5abb91d9876 100644
--- a/src/mesa/drivers/dri/r300/Makefile
+++ b/src/mesa/drivers/dri/r300/Makefile
@@ -5,7 +5,6 @@ TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = r300_dri.so
-DEFINES += -DCOMPILE_R300 -DGLX_DIRECT_RENDERING -DR200_MERGED=0
MINIGLX_SOURCES = server/radeon_dri.c
@@ -70,7 +69,8 @@ C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
X86_SOURCES =
#r200_vtxtmp_x86.S
-DEFINES += -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300
+DRIVER_DEFINES = -DCOMPILE_R300 -DGLX_DIRECT_RENDERING -DR200_MERGED=0 \
+ -DRADEON_COMMON=1 -DRADEON_COMMON_FOR_R300
SYMLINKS = \
server/radeon_dri.c \
diff --git a/src/mesa/drivers/dri/r300/r300_cmdbuf.c b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
index 09f7669bd71..f39f71584ce 100644
--- a/src/mesa/drivers/dri/r300/r300_cmdbuf.c
+++ b/src/mesa/drivers/dri/r300/r300_cmdbuf.c
@@ -337,8 +337,10 @@ void r300InitCmdBuf(r300ContextPtr r300)
r300->hw.unk4260.cmd[0] = cmdpacket0(0x4260, 3);
ALLOC_STATE( unk4274, always, 5, "unk4274", 0 );
r300->hw.unk4274.cmd[0] = cmdpacket0(0x4274, 4);
- ALLOC_STATE( unk4288, always, 6, "unk4288", 0 );
- r300->hw.unk4288.cmd[0] = cmdpacket0(0x4288, 5);
+ ALLOC_STATE( unk4288, always, 4, "unk4288", 0 );
+ r300->hw.unk4288.cmd[0] = cmdpacket0(0x4288, 3);
+ ALLOC_STATE( fogp, always, 3, "fogp", 0 );
+ r300->hw.fogp.cmd[0] = cmdpacket0(R300_RE_FOG_SCALE, 2);
ALLOC_STATE( unk42A0, always, 2, "unk42A0", 0 );
r300->hw.unk42A0.cmd[0] = cmdpacket0(0x42A0, 1);
ALLOC_STATE( zbs, always, R300_ZBS_CMDSIZE, "zbs", 0 );
@@ -374,10 +376,10 @@ void r300InitCmdBuf(r300ContextPtr r300)
r300->hw.fpi[2].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR2_0, 1);
ALLOC_STATE( fpi[3], variable, R300_FPI_CMDSIZE, "fpi/3", 3 );
r300->hw.fpi[3].cmd[R300_FPI_CMD_0] = cmdpacket0(R300_PFS_INSTR3_0, 1);
- ALLOC_STATE( unk4BC0, always, 2, "unk4BC0", 0 );
- r300->hw.unk4BC0.cmd[0] = cmdpacket0(0x4BC0, 1);
- ALLOC_STATE( unk4BC8, always, 4, "unk4BC8", 0 );
- r300->hw.unk4BC8.cmd[0] = cmdpacket0(0x4BC8, 3);
+ ALLOC_STATE( fogs, always, R300_FOGS_CMDSIZE, "fogs", 0 );
+ r300->hw.fogs.cmd[R300_FOGS_CMD_0] = cmdpacket0(R300_RE_FOG_STATE, 1);
+ ALLOC_STATE( fogc, always, R300_FOGC_CMDSIZE, "fogc", 0 );
+ r300->hw.fogc.cmd[R300_FOGC_CMD_0] = cmdpacket0(R300_FOG_COLOR_R, 3);
ALLOC_STATE( at, always, R300_AT_CMDSIZE, "at", 0 );
r300->hw.at.cmd[R300_AT_CMD_0] = cmdpacket0(R300_PP_ALPHA_TEST, 2);
ALLOC_STATE( unk4BD8, always, 2, "unk4BD8", 0 );
@@ -478,6 +480,7 @@ void r300InitCmdBuf(r300ContextPtr r300)
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4260);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4274);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4288);
+ insert_at_tail(&r300->hw.atomlist, &r300->hw.fogp);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42A0);
insert_at_tail(&r300->hw.atomlist, &r300->hw.zbs);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk42B4);
@@ -495,8 +498,8 @@ void r300InitCmdBuf(r300ContextPtr r300)
insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[1]);
insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[2]);
insert_at_tail(&r300->hw.atomlist, &r300->hw.fpi[3]);
- insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC0);
- insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BC8);
+ insert_at_tail(&r300->hw.atomlist, &r300->hw.fogs);
+ insert_at_tail(&r300->hw.atomlist, &r300->hw.fogc);
insert_at_tail(&r300->hw.atomlist, &r300->hw.at);
insert_at_tail(&r300->hw.atomlist, &r300->hw.unk4BD8);
insert_at_tail(&r300->hw.atomlist, &r300->hw.fpp);
@@ -541,9 +544,9 @@ void r300InitCmdBuf(r300ContextPtr r300)
size = 64*256;
if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) {
- fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%d\n",
+ fprintf(stderr, "sizeof(drm_r300_cmd_header_t)=%ld\n",
sizeof(drm_r300_cmd_header_t));
- fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%d\n",
+ fprintf(stderr, "sizeof(drm_radeon_cmd_buffer_t)=%ld\n",
sizeof(drm_radeon_cmd_buffer_t));
fprintf(stderr,
"Allocating %d bytes command buffer (max state is %d bytes)\n",
diff --git a/src/mesa/drivers/dri/r300/r300_context.c b/src/mesa/drivers/dri/r300/r300_context.c
index 4943d549973..cadb27ba8b9 100644
--- a/src/mesa/drivers/dri/r300/r300_context.c
+++ b/src/mesa/drivers/dri/r300/r300_context.c
@@ -372,6 +372,61 @@ GLboolean r300CreateContext(const __GLcontextModes * glVisual,
return GL_TRUE;
}
+static void r300FreeGartAllocations(r300ContextPtr r300)
+{
+ int i, ret, tries=0, done_age;
+ drm_radeon_mem_free_t memfree;
+
+ memfree.region = RADEON_MEM_REGION_GART;
+
+#ifdef USER_BUFFERS
+ done_age = radeonGetAge((radeonContextPtr)r300);
+
+ for (i = r300->rmm->u_last; i > 0; i--) {
+ if (r300->rmm->u_list[i].ptr == NULL) {
+ continue;
+ }
+
+ assert(r300->rmm->u_list[i].pending);
+ assert(r300->rmm->u_list[i].h_pending == 0);
+
+ tries = 0;
+ while(r300->rmm->u_list[i].age > done_age && tries++ < 1000) {
+ usleep(10);
+ done_age = radeonGetAge((radeonContextPtr)r300);
+ }
+ if (tries >= 1000) {
+ WARN_ONCE("Failed to idle region!");
+ }
+
+ memfree.region_offset = (char *)r300->rmm->u_list[i].ptr -
+ (char *)r300->radeon.radeonScreen->gartTextures.map;
+
+ ret = drmCommandWrite(r300->radeon.radeonScreen->driScreen->fd,
+ DRM_RADEON_FREE, &memfree, sizeof(memfree));
+ if (ret) {
+ fprintf(stderr, "Failed to free at %p\nret = %s\n",
+ r300->rmm->u_list[i].ptr, strerror(-ret));
+ } else {
+ if (i == r300->rmm->u_last)
+ r300->rmm->u_last--;
+
+ r300->rmm->u_list[i].pending = 0;
+ r300->rmm->u_list[i].ptr = NULL;
+ if (r300->rmm->u_list[i].fb) {
+ LOCK_HARDWARE(&(r300->radeon));
+ ret = mmFreeMem(r300->rmm->u_list[i].fb);
+ UNLOCK_HARDWARE(&(r300->radeon));
+ if (ret) fprintf(stderr, "failed to free!\n");
+ r300->rmm->u_list[i].fb = NULL;
+ }
+ r300->rmm->u_list[i].ref_count = 0;
+ }
+ }
+ r300->rmm->u_head = i;
+#endif /* USER_BUFFERS */
+}
+
/* Destroy the device specific context.
*/
void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
@@ -403,12 +458,11 @@ void r300DestroyContext(__DRIcontextPrivate * driContextPriv)
_ac_DestroyContext(r300->radeon.glCtx);
_swrast_DestroyContext(r300->radeon.glCtx);
- r300ReleaseArrays(r300->radeon.glCtx);
if (r300->dma.current.buf) {
r300ReleaseDmaRegion(r300, &r300->dma.current, __FUNCTION__ );
- r300FlushCmdBuf(r300, __FUNCTION__ );
}
-
+ r300FlushCmdBuf(r300, __FUNCTION__);
+ r300FreeGartAllocations(r300);
r300DestroyCmdBuf(r300);
if (radeon->state.scissor.pClipRects) {
diff --git a/src/mesa/drivers/dri/r300/r300_context.h b/src/mesa/drivers/dri/r300/r300_context.h
index 176341d7715..7ff805fd5d3 100644
--- a/src/mesa/drivers/dri/r300/r300_context.h
+++ b/src/mesa/drivers/dri/r300/r300_context.h
@@ -47,11 +47,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "colormac.h"
#include "radeon_context.h"
-/* PPC doesnt support 16 bit elts ... */
-#ifndef MESA_BIG_ENDIAN
#define USER_BUFFERS
#define RADEON_VTXFMT_A
#define HW_VBOS
+
+/* We don't handle 16 bits elts swapping yet */
+#ifdef MESA_BIG_ENDIAN
+#define FORCE_32BITS_ELTS
#endif
//#define OPTIMIZE_ELTS
@@ -346,6 +348,21 @@ struct r300_state_atom {
#define R300_FPP_PARAM_0 1
#define R300_FPP_CMDSIZE (32*4+1)
+#define R300_FOGS_CMD_0 0
+#define R300_FOGS_STATE 1
+#define R300_FOGS_CMDSIZE 2
+
+#define R300_FOGC_CMD_0 0
+#define R300_FOGC_R 1
+#define R300_FOGC_G 2
+#define R300_FOGC_B 3
+#define R300_FOGC_CMDSIZE 4
+
+#define R300_FOGP_CMD_0 0
+#define R300_FOGP_SCALE 1
+#define R300_FOGP_START 2
+#define R300_FOGP_CMDSIZE 3
+
#define R300_AT_CMD_0 0
#define R300_AT_ALPHA_TEST 1
#define R300_AT_UNKNOWN 2
@@ -432,6 +449,8 @@ struct r300_hw_state {
struct r300_state_atom unk4260; /* (4260) */
struct r300_state_atom unk4274; /* (4274) */
struct r300_state_atom unk4288; /* (4288) */
+ struct r300_state_atom fogp; /* fog parameters (4294) */
+ struct r300_state_atom unk429C; /* (429C) */
struct r300_state_atom unk42A0; /* (42A0) */
struct r300_state_atom zbs; /* zbias (42A4) */
struct r300_state_atom unk42B4; /* (42B4) */
@@ -446,8 +465,8 @@ struct r300_hw_state {
struct r300_state_atom fpt; /* texi - (4620) */
struct r300_state_atom unk46A4; /* (46A4) */
struct r300_state_atom fpi[4]; /* fp instructions (46C0/47C0/48C0/49C0) */
- struct r300_state_atom unk4BC0; /* (4BC0) */
- struct r300_state_atom unk4BC8; /* (4BC8) */
+ struct r300_state_atom fogs; /* fog state (4BC0) */
+ struct r300_state_atom fogc; /* fog color (4BC8) */
struct r300_state_atom at; /* alpha test (4BD4) */
struct r300_state_atom unk4BD8; /* (4BD8) */
struct r300_state_atom fpp; /* 0x4C00 and following */
@@ -532,7 +551,8 @@ struct r300_vap_reg_state {
/* Vertex shader state */
/* Perhaps more if we store programs in vmem? */
-#define VSF_MAX_FRAGMENT_LENGTH (256*4)
+/* drm_r300_cmd_header_t->vpu->count is unsigned char */
+#define VSF_MAX_FRAGMENT_LENGTH (255*4)
/* Can be tested with colormat currently. */
#define VSF_MAX_FRAGMENT_TEMPS (14)
@@ -759,7 +779,7 @@ struct r300_state {
GLuint *Elts;
struct r300_dma_region elt_dma;
- GLuint render_inputs; /* actual render inputs that R300 was configured for.
+ DECLARE_RENDERINPUTS(render_inputs_bitset); /* actual render inputs that R300 was configured for.
They are the same as tnl->render_inputs for fixed pipeline */
struct {
@@ -810,6 +830,7 @@ struct r300_context {
#endif
GLboolean texmicrotile;
+ GLboolean span_dlocking;
};
struct r300_buffer_object {
diff --git a/src/mesa/drivers/dri/r300/r300_fragprog.c b/src/mesa/drivers/dri/r300/r300_fragprog.c
index db509059dd7..e045f0c6a1e 100644
--- a/src/mesa/drivers/dri/r300/r300_fragprog.c
+++ b/src/mesa/drivers/dri/r300/r300_fragprog.c
@@ -1039,7 +1039,7 @@ static GLboolean parse_program(struct r300_fragment_program *rp)
const struct prog_instruction *inst = mp->Base.Instructions;
struct prog_instruction *fpi;
pfs_reg_t src[3], dest, temp;
- int flags, mask;
+ int flags, mask = 0;
if (!inst || inst[0].Opcode == OPCODE_END) {
ERROR("empty program?\n");
diff --git a/src/mesa/drivers/dri/r300/r300_ioctl.c b/src/mesa/drivers/dri/r300/r300_ioctl.c
index 0115d622a99..159285962d2 100644
--- a/src/mesa/drivers/dri/r300/r300_ioctl.c
+++ b/src/mesa/drivers/dri/r300/r300_ioctl.c
@@ -380,10 +380,16 @@ static void r300EmitClearState(GLcontext * ctx)
int i;
LOCAL_VARS;
+
R300_STATECHANGE(r300, vir[0]);
reg_start(R300_VAP_INPUT_ROUTE_0_0, 0);
e32(0x21030003);
+ /* disable fog */
+ R300_STATECHANGE(r300, fogs);
+ reg_start(R300_RE_FOG_STATE, 0);
+ e32(0x0);
+
R300_STATECHANGE(r300, vir[1]);
reg_start(R300_VAP_INPUT_ROUTE_1_0, 0);
e32(0xF688F688);
@@ -553,7 +559,7 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all,
#ifdef CB_DPATH
/* Make sure it fits there. */
- r300EnsureCmdBufSpace(r300, 419*3, __FUNCTION__);
+ r300EnsureCmdBufSpace(r300, 421*3, __FUNCTION__);
if(flags || bits)
r300EmitClearState(ctx);
#endif
diff --git a/src/mesa/drivers/dri/r300/r300_maos.c b/src/mesa/drivers/dri/r300/r300_maos.c
index 1aa005c7207..6b8365e6d9e 100644
--- a/src/mesa/drivers/dri/r300/r300_maos.c
+++ b/src/mesa/drivers/dri/r300/r300_maos.c
@@ -252,6 +252,43 @@ void r300EmitElts(GLcontext * ctx, void *elts, unsigned long n_elts, int elt_siz
memcpy(out, elts, n_elts * elt_size);
}
+ /* Mesa assumes that all missing components are from (0, 0, 0, 1) */
+#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT))
+
+#define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \
+ | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT))
+
+
+static GLuint t_comps(GLuint aos_size)
+{
+ GLuint mask;
+ mask = (1 << (aos_size*3)) - 1;
+ return (ALL_COMPONENTS & mask) | (ALL_DEFAULT & ~mask);
+}
+
+static GLuint fix_comps(GLuint dw, int fmt)
+{
+#ifdef MESA_BIG_ENDIAN
+ if (fmt == 2) {
+ GLuint dw_temp = 0;
+
+ dw_temp |= ((dw >> R300_INPUT_ROUTE_X_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_W_SHIFT;
+ dw_temp |= ((dw >> R300_INPUT_ROUTE_Y_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_Z_SHIFT;
+ dw_temp |= ((dw >> R300_INPUT_ROUTE_Z_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_Y_SHIFT;
+ dw_temp |= ((dw >> R300_INPUT_ROUTE_W_SHIFT) & R300_INPUT_ROUTE_SELECT_MASK) << R300_INPUT_ROUTE_X_SHIFT;
+
+ return dw_temp;
+ }
+#endif /* MESA_BIG_ENDIAN */
+ return dw;
+
+}
+
/* Emit vertex data to GART memory (unless immediate mode)
* Route inputs to the vertex processor
*/
@@ -264,12 +301,14 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
//struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint nr = 0;
GLuint count = VB->Count;
- GLuint dw,mask;
+ GLuint dw;
GLuint vic_1 = 0; /* R300_VAP_INPUT_CNTL_1 */
GLuint aa_vap_reg = 0; /* VAP register assignment */
GLuint i;
- GLuint inputs = 0;
-
+ DECLARE_RENDERINPUTS(inputs_bitset);
+
+ RENDERINPUTS_ZERO( inputs_bitset );
+
#define CONFIGURE_AOS(r, f, v, sz, cn) { \
if (RADEON_DEBUG & DEBUG_STATE) \
fprintf(stderr, "Enabling "#v "\n"); \
@@ -300,23 +339,23 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
GLuint InputsRead = CURRENT_VERTEX_SHADER(ctx)->Base.InputsRead;
struct r300_vertex_program *prog=(struct r300_vertex_program *)CURRENT_VERTEX_SHADER(ctx);
if (InputsRead & (1<<VERT_ATTRIB_POS)) {
- inputs |= _TNL_BIT_POS;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_POS );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_POS];
}
if (InputsRead & (1<<VERT_ATTRIB_NORMAL)) {
- inputs |= _TNL_BIT_NORMAL;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_NORMAL );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_NORMAL];
}
if (InputsRead & (1<<VERT_ATTRIB_COLOR0)) {
- inputs |= _TNL_BIT_COLOR0;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_COLOR0 );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR0];
}
if (InputsRead & (1<<VERT_ATTRIB_COLOR1)) {
- inputs |= _TNL_BIT_COLOR1;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_COLOR1 );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_COLOR1];
}
if (InputsRead & (1<<VERT_ATTRIB_FOG)) {
- inputs |= _TNL_BIT_FOG;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_FOG );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_FOG];
}
if(ctx->Const.MaxTextureUnits > 8) { /* Not sure if this can even happen... */
@@ -325,17 +364,17 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
}
for (i=0;i<ctx->Const.MaxTextureUnits;i++) {
if (InputsRead & (1<<(VERT_ATTRIB_TEX0+i))) {
- inputs |= _TNL_BIT_TEX0<<i;
+ RENDERINPUTS_SET( inputs_bitset, _TNL_ATTRIB_TEX(i) );
rmesa->state.aos[nr++].aos_reg = prog->inputs[VERT_ATTRIB_TEX0+i];
}
}
nr = 0;
} else {
- inputs = TNL_CONTEXT(ctx)->render_inputs;
+ RENDERINPUTS_COPY( inputs_bitset, TNL_CONTEXT(ctx)->render_inputs_bitset );
}
- rmesa->state.render_inputs = inputs;
+ RENDERINPUTS_COPY( rmesa->state.render_inputs_bitset, inputs_bitset );
- if (inputs & _TNL_BIT_POS) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_POS )) {
CONFIGURE_AOS(i_coords, AOS_FORMAT_FLOAT,
VB->AttribPtr[VERT_ATTRIB_POS],
immd ? 4 : VB->AttribPtr[VERT_ATTRIB_POS].size,
@@ -344,7 +383,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
vic_1 |= R300_INPUT_CNTL_POS;
}
- if (inputs & _TNL_BIT_NORMAL) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_NORMAL )) {
CONFIGURE_AOS(i_normal, AOS_FORMAT_FLOAT,
VB->AttribPtr[VERT_ATTRIB_NORMAL],
immd ? 4 : VB->AttribPtr[VERT_ATTRIB_NORMAL].size,
@@ -353,7 +392,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
vic_1 |= R300_INPUT_CNTL_NORMAL;
}
- if (inputs & _TNL_BIT_COLOR0) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR0 )) {
int emitsize=4;
if (!immd) {
@@ -376,7 +415,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
vic_1 |= R300_INPUT_CNTL_COLOR;
}
- if (inputs & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR1 )) {
int emitsize=4;
if (!immd) {
@@ -398,7 +437,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
}
#if 0
- if (inputs & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_FOG )) {
CONFIGURE_AOS( AOS_FORMAT_FLOAT,
VB->FogCoordPtr,
immd ? 4 : VB->FogCoordPtr->size,
@@ -408,7 +447,7 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
r300->state.texture.tc_count = 0;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (inputs & (_TNL_BIT_TEX0 << i)) {
+ if (RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_TEX(i) )) {
CONFIGURE_AOS(i_tex[i], AOS_FORMAT_FLOAT,
VB->AttribPtr[VERT_ATTRIB_TEX0+i],
immd ? 4 : VB->AttribPtr[VERT_ATTRIB_TEX0+i].size,
@@ -467,17 +506,6 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->packet0.count = (nr+1)>>1;
- /* Mesa assumes that all missing components are from (0, 0, 0, 1) */
-#define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT))
-
-#define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \
- | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT))
-
R300_STATECHANGE(r300, vir[1]);
for(i=0; i < nr; i++)
@@ -486,33 +514,22 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
r300->state.aos[i].aos_size=/*3*/4; /* XXX */
}
-
- for(i=0;i+1<nr;i+=2){
+ for (i=0;i+1<nr;i+=2) {
/* do i first.. */
- mask=(1<<(r300->state.aos[i].aos_size*3))-1;
- dw=(ALL_COMPONENTS & mask)
- | (ALL_DEFAULT & ~mask)
- | R300_INPUT_ROUTE_ENABLE;
-
+ dw = fix_comps(t_comps(r300->state.aos[i].aos_size), r300->state.aos[i].aos_format) | R300_INPUT_ROUTE_ENABLE;
/* i+1 */
- mask=(1<<(r300->state.aos[i+1].aos_size*3))-1;
- dw|=(
- (ALL_COMPONENTS & mask)
- | (ALL_DEFAULT & ~mask)
- | R300_INPUT_ROUTE_ENABLE
- )<<16;
-
+ dw |= (fix_comps(t_comps(r300->state.aos[i+1].aos_size), r300->state.aos[i+1].aos_format) | R300_INPUT_ROUTE_ENABLE) << 16;
+
//fprintf(stderr, "vir1 dw=%08x\n", dw);
r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(i>>1)]=dw;
- }
- if(nr & 1){
- mask=(1<<(r300->state.aos[nr-1].aos_size*3))-1;
- dw=(ALL_COMPONENTS & mask)
- | (ALL_DEFAULT & ~mask)
- | R300_INPUT_ROUTE_ENABLE;
- r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw;
+ }
+ if (nr & 1) {
+ dw = fix_comps(t_comps(r300->state.aos[nr-1].aos_size), r300->state.aos[nr-1].aos_format) | R300_INPUT_ROUTE_ENABLE;
+
//fprintf(stderr, "vir1 dw=%08x\n", dw);
- }
+ r300->hw.vir[1].cmd[R300_VIR_CNTL_0+(nr>>1)]=dw;
+ }
+
/* Set the rest of INPUT_ROUTE_1 to 0 */
//for(i=((count+1)>>1); i<8; i++)r300->hw.vir[1].cmd[R300_VIR_CNTL_0+i]=0x0;
((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->packet0.count = (nr+1)>>1;
@@ -531,17 +548,17 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
#if 0
r300->hw.vic.cmd[R300_VIC_CNTL_1]=0;
- if(r300->state.render_inputs & _TNL_BIT_POS)
+ if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_POS ))
r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_POS;
- if(r300->state.render_inputs & _TNL_BIT_NORMAL)
+ if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_NORMAL ))
r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_NORMAL;
- if(r300->state.render_inputs & _TNL_BIT_COLOR0)
+ if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_COLOR0 ))
r300->hw.vic.cmd[R300_VIC_CNTL_1]|=R300_INPUT_CNTL_COLOR;
for(i=0;i < ctx->Const.MaxTextureUnits;i++)
- if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i))
+ if(RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_TEX(i) ))
r300->hw.vic.cmd[R300_VIC_CNTL_1]|=(R300_INPUT_CNTL_TC0<<i);
#endif
@@ -573,15 +590,15 @@ void r300EmitArrays(GLcontext * ctx, GLboolean immd)
if(OutputsWritten & (1<<(VERT_RESULT_TEX0+i)))
r300->hw.vof.cmd[R300_VOF_CNTL_1] |= (4<<(3*i));
} else {
- if(inputs & _TNL_BIT_POS)
+ if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_POS ))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT;
- if(inputs & _TNL_BIT_COLOR0)
+ if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR0 ))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
- if(inputs & _TNL_BIT_COLOR1)
+ if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_COLOR1 ))
r300->hw.vof.cmd[R300_VOF_CNTL_0] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT;
for(i=0;i < ctx->Const.MaxTextureUnits;i++)
- if(inputs & (_TNL_BIT_TEX0<<i))
+ if(RENDERINPUTS_TEST( inputs_bitset, _TNL_ATTRIB_TEX(i) ))
r300->hw.vof.cmd[R300_VOF_CNTL_1]|=(4<<(3*i));
}
diff --git a/src/mesa/drivers/dri/r300/r300_reg.h b/src/mesa/drivers/dri/r300/r300_reg.h
index c78462af2ed..4afe4f239c2 100644
--- a/src/mesa/drivers/dri/r300/r300_reg.h
+++ b/src/mesa/drivers/dri/r300/r300_reg.h
@@ -517,6 +517,10 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_PM_BACK_LINE (1 << 7)
# define R300_PM_BACK_FILL (1 << 8)
+/* Fog parameters */
+#define R300_RE_FOG_SCALE 0x4294
+#define R300_RE_FOG_START 0x4298
+
/* Not sure why there are duplicate of factor and constant values.
My best guess so far is that there are seperate zbiases for test and write.
Ordering might be wrong.
@@ -1113,7 +1117,17 @@ I am fairly certain that they are correct unless stated otherwise in comments.
# define R300_FPI2_UNKNOWN_31 (1 << 31)
/* END */
-/* gap */
+/* Fog state and color */
+#define R300_RE_FOG_STATE 0x4BC0
+# define R300_FOG_ENABLE (1 << 0)
+# define R300_FOG_MODE_LINEAR (0 << 1)
+# define R300_FOG_MODE_EXP (1 << 1)
+# define R300_FOG_MODE_EXP2 (2 << 1)
+# define R300_FOG_MODE_MASK (3 << 1)
+#define R300_FOG_COLOR_R 0x4BC8
+#define R300_FOG_COLOR_G 0x4BCC
+#define R300_FOG_COLOR_B 0x4BD0
+
#define R300_PP_ALPHA_TEST 0x4BD4
# define R300_REF_ALPHA_MASK 0x000000ff
# define R300_ALPHA_TEST_FAIL (0 << 8)
diff --git a/src/mesa/drivers/dri/r300/r300_render.c b/src/mesa/drivers/dri/r300/r300_render.c
index a0375f90227..f86a439bc29 100644
--- a/src/mesa/drivers/dri/r300/r300_render.c
+++ b/src/mesa/drivers/dri/r300/r300_render.c
@@ -382,7 +382,6 @@ GLboolean r300_run_vb_render(GLcontext *ctx,
r300UpdateShaders(rmesa);
if (rmesa->state.VB.LockCount == 0 || 1) {
- r300ReleaseArrays(ctx);
r300EmitArrays(ctx, GL_FALSE);
r300UpdateShaderStates(rmesa);
@@ -446,6 +445,7 @@ GLboolean r300_run_vb_render(GLcontext *ctx,
#ifdef USER_BUFFERS
r300UseArrays(ctx);
#endif
+ r300ReleaseArrays(ctx);
return GL_FALSE;
}
@@ -462,19 +462,19 @@ int r300Fallback(GLcontext *ctx)
{
int i;
- //FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?)
+ FALLBACK_IF(ctx->RenderMode != GL_RENDER); // We do not do SELECT or FEEDBACK (yet ?)
#if 0 /* These should work now.. */
FALLBACK_IF(ctx->Color.DitherFlag);
FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
+ FALLBACK_IF(ctx->Fog.Enabled);
#endif
FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
//FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
- //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this
//FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going
FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
diff --git a/src/mesa/drivers/dri/r300/r300_state.c b/src/mesa/drivers/dri/r300/r300_state.c
index d4dafe62a73..70d42c2ea3b 100644
--- a/src/mesa/drivers/dri/r300/r300_state.c
+++ b/src/mesa/drivers/dri/r300/r300_state.c
@@ -417,6 +417,24 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
case GL_TEXTURE_3D:
break;
+ case GL_FOG:
+ R300_STATECHANGE(r300, fogs);
+ if (state) {
+ r300->hw.fogs.cmd[R300_FOGS_STATE] |=
+ R300_FOG_ENABLE;
+
+ ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL );
+ ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+ ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+ ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ } else {
+ r300->hw.fogs.cmd[R300_FOGS_STATE] &=
+ ~R300_FOG_ENABLE;
+ }
+
+ break;
+
case GL_ALPHA_TEST:
R300_STATECHANGE(r300, at);
if (state) {
@@ -640,6 +658,101 @@ static void r300ColorMask(GLcontext* ctx,
}
/* =============================================================
+ * Fog
+ */
+static void r300Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+ r300ContextPtr r300 = R300_CONTEXT(ctx);
+ union { int i; float f; } fogScale, fogStart;
+
+ (void) param;
+
+ fogScale.i = r300->hw.fogp.cmd[R300_FOGP_SCALE];
+ fogStart.i = r300->hw.fogp.cmd[R300_FOGP_START];
+
+ switch (pname) {
+ case GL_FOG_MODE:
+ if (!ctx->Fog.Enabled)
+ return;
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ R300_STATECHANGE(r300, fogs);
+ r300->hw.fogs.cmd[R300_FOGS_STATE] =
+ (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_LINEAR;
+
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ fogScale.f = -1.0;
+ fogStart.f = 1.0;
+ }
+ else {
+ fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start);
+ fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start);
+ }
+ break;
+ case GL_EXP:
+ R300_STATECHANGE(r300, fogs);
+ r300->hw.fogs.cmd[R300_FOGS_STATE] =
+ (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP;
+ fogScale.f = 0.0933*ctx->Fog.Density;
+ fogStart.f = 0.0;
+ break;
+ case GL_EXP2:
+ R300_STATECHANGE(r300, fogs);
+ r300->hw.fogs.cmd[R300_FOGS_STATE] =
+ (r300->hw.fogs.cmd[R300_FOGS_STATE] & ~R300_FOG_MODE_MASK) | R300_FOG_MODE_EXP2;
+ fogScale.f = 0.3*ctx->Fog.Density;
+ fogStart.f = 0.0;
+ default:
+ return;
+ }
+ break;
+ case GL_FOG_DENSITY:
+ switch (ctx->Fog.Mode) {
+ case GL_EXP:
+ fogScale.f = 0.0933*ctx->Fog.Density;
+ fogStart.f = 0.0;
+ break;
+ case GL_EXP2:
+ fogScale.f = 0.3*ctx->Fog.Density;
+ fogStart.f = 0.0;
+ default:
+ break;
+ }
+ break;
+ case GL_FOG_START:
+ case GL_FOG_END:
+ if (ctx->Fog.Mode == GL_LINEAR) {
+ if (ctx->Fog.Start == ctx->Fog.End) {
+ fogScale.f = -1.0;
+ fogStart.f = 1.0;
+ }
+ else {
+ fogScale.f = 1.0 / (ctx->Fog.End-ctx->Fog.Start);
+ fogStart.f = -ctx->Fog.Start / (ctx->Fog.End-ctx->Fog.Start);
+ }
+ }
+ break;
+ case GL_FOG_COLOR:
+ R300_STATECHANGE(r300, fogc);
+ r300->hw.fogc.cmd[R300_FOGC_R] = (GLuint) (ctx->Fog.Color[0]*1023.0F) & 0x3FF;
+ r300->hw.fogc.cmd[R300_FOGC_G] = (GLuint) (ctx->Fog.Color[1]*1023.0F) & 0x3FF;
+ r300->hw.fogc.cmd[R300_FOGC_B] = (GLuint) (ctx->Fog.Color[2]*1023.0F) & 0x3FF;
+ break;
+ case GL_FOG_COORD_SRC:
+ break;
+ default:
+ return;
+ }
+
+ if (fogScale.i != r300->hw.fogp.cmd[R300_FOGP_SCALE] ||
+ fogStart.i != r300->hw.fogp.cmd[R300_FOGP_START]) {
+ R300_STATECHANGE(r300, fogp);
+ r300->hw.fogp.cmd[R300_FOGP_SCALE] = fogScale.i;
+ r300->hw.fogp.cmd[R300_FOGP_START] = fogStart.i;
+ }
+}
+
+/* =============================================================
* Point state
*/
static void r300PointSize(GLcontext * ctx, GLfloat size)
@@ -750,8 +863,8 @@ static void r300StencilFuncSeparate(GLcontext * ctx, GLenum face,
GLenum func, GLint ref, GLuint mask)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
- (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+ GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
+ ((ctx->Stencil.ValueMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
GLuint flag;
@@ -777,7 +890,7 @@ static void r300StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
R300_STATECHANGE(rmesa, zs);
rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT);
- rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
+ rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= (ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
}
@@ -807,9 +920,9 @@ static void r300ClearStencil(GLcontext * ctx, GLint s)
r300ContextPtr rmesa = R300_CONTEXT(ctx);
rmesa->state.stencil.clear =
- ((GLuint) ctx->Stencil.Clear |
+ ((GLuint) (ctx->Stencil.Clear & 0xff) |
(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) |
- (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT));
+ ((ctx->Stencil.WriteMask[0] & 0xff) << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT));
}
/* =============================================================
@@ -1157,6 +1270,15 @@ void r300_setup_textures(GLcontext *ctx)
fprintf(stderr, "TX_ENABLE: %08x last_hw_tmu=%d\n", r300->hw.txe.cmd[R300_TXE_ENABLE], last_hw_tmu);
}
+union r300_outputs_written {
+ GLuint vp_outputs; /* hw_tcl_on */
+ DECLARE_RENDERINPUTS(index_bitset); /* !hw_tcl_on */
+};
+
+#define R300_OUTPUTS_WRITTEN_TEST(ow, vp_result, tnl_attrib) \
+ ((hw_tcl_on) ? (ow).vp_outputs & (1 << (vp_result)) : \
+ RENDERINPUTS_TEST( (ow.index_bitset), (tnl_attrib) ))
+
void r300_setup_rs_unit(GLcontext *ctx)
{
r300ContextPtr r300 = R300_CONTEXT(ctx);
@@ -1171,16 +1293,16 @@ void r300_setup_rs_unit(GLcontext *ctx)
0x00,
0x00
};
- GLuint OutputsWritten;
+ union r300_outputs_written OutputsWritten;
GLuint InputsRead;
int fp_reg, high_rr;
int in_texcoords, col_interp_nr;
int i;
if(hw_tcl_on)
- OutputsWritten = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten;
+ OutputsWritten.vp_outputs = CURRENT_VERTEX_SHADER(ctx)->Base.OutputsWritten;
else
- OutputsWritten = r300->state.render_inputs;
+ RENDERINPUTS_COPY( OutputsWritten.index_bitset, r300->state.render_inputs_bitset );
if (ctx->FragmentProgram._Current)
InputsRead = ctx->FragmentProgram._Current->Base.InputsRead;
@@ -1211,7 +1333,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
| (fp_reg << R300_RS_ROUTE_DEST_SHIFT);
high_rr = fp_reg;
- if (!(OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i)))) {
+ if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) )) {
/* Passing invalid data here can lock the GPU. */
WARN_ONCE("fragprog wants coords for tex%d, vp doesn't provide them!\n", i);
//_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base);
@@ -1221,12 +1343,12 @@ void r300_setup_rs_unit(GLcontext *ctx)
fp_reg++;
}
/* Need to count all coords enabled at vof */
- if (OutputsWritten & (hw_tcl_on ? (1 << (VERT_RESULT_TEX0+i)) : (_TNL_BIT_TEX0<<i)))
+ if (R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_TEX0+i, _TNL_ATTRIB_TEX(i) ))
in_texcoords++;
}
if (InputsRead & FRAG_BIT_COL0) {
- if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL0) : _TNL_BIT_COLOR0))) {
+ if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL0, _TNL_ATTRIB_COLOR0 )) {
WARN_ONCE("fragprog wants col0, vp doesn't provide it\n");
goto out; /* FIXME */
//_mesa_print_program(&CURRENT_VERTEX_SHADER(ctx)->Base);
@@ -1242,7 +1364,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
out:
if (InputsRead & FRAG_BIT_COL1) {
- if (!(OutputsWritten & (hw_tcl_on ? (1<<VERT_RESULT_COL1) : _TNL_BIT_COLOR1))) {
+ if (!R300_OUTPUTS_WRITTEN_TEST( OutputsWritten, VERT_RESULT_COL1, _TNL_ATTRIB_COLOR1 )) {
WARN_ONCE("fragprog wants col1, vp doesn't provide it\n");
//exit(-1);
}
@@ -1281,6 +1403,7 @@ void r300_setup_rs_unit(GLcontext *ctx)
#define bump_vpu_count(ptr, new_count) do{\
drm_r300_cmd_header_t* _p=((drm_r300_cmd_header_t*)(ptr));\
int _nc=(new_count)/4; \
+ assert(_nc < 256); \
if(_nc>_p->vpu.count)_p->vpu.count=_nc;\
}while(0)
@@ -1402,7 +1525,7 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300)
)
o_reg += 2;
- if (r300->state.render_inputs & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_COLOR1 )) {
WRITE_OP(
EASY_VSF_OP(MUL, o_reg++, ALL, RESULT),
VSF_REG(r300->state.vap_reg.i_color[1]),
@@ -1413,7 +1536,7 @@ static void r300GenerateSimpleVertexShader(r300ContextPtr r300)
/* Pass through texture coordinates, if any */
for(i=0;i < r300->radeon.glCtx->Const.MaxTextureUnits;i++)
- if(r300->state.render_inputs & (_TNL_BIT_TEX0<<i)){
+ if (RENDERINPUTS_TEST( r300->state.render_inputs_bitset, _TNL_ATTRIB_TEX(i) )){
// fprintf(stderr, "i_tex[%d]=%d\n", i, r300->state.vap_reg.i_tex[i]);
WRITE_OP(
EASY_VSF_OP(MUL, o_reg++ /* 2+i */, ALL, RESULT),
@@ -1870,7 +1993,8 @@ void r300ResetHwState(r300ContextPtr r300)
r300->hw.gb_misc.cmd[R300_GB_MISC_TILE_CONFIG] = R300_GB_TILE_ENABLE
| R300_GB_TILE_PIPE_COUNT_RV300
| R300_GB_TILE_SIZE_16;
- r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = 0x00000000;
+ /* set to 0 when fog is disabled? */
+ r300->hw.gb_misc.cmd[R300_GB_MISC_SELECT] = R300_GB_FOG_SELECT_1_1_W;
r300->hw.gb_misc.cmd[R300_GB_MISC_AA_CONFIG] = 0x00000000; /* No antialiasing */
//r300->hw.txe.cmd[R300_TXE_ENABLE] = 0;
@@ -1907,9 +2031,6 @@ void r300ResetHwState(r300ContextPtr r300)
r300PolygonMode(ctx, GL_BACK, ctx->Polygon.BackMode);
r300->hw.unk4288.cmd[2] = 0x00000001;
r300->hw.unk4288.cmd[3] = 0x00000000;
- r300->hw.unk4288.cmd[4] = 0x00000000;
- r300->hw.unk4288.cmd[5] = 0x00000000;
-
r300->hw.unk42A0.cmd[1] = 0x00000000;
r300PolygonOffset(ctx, ctx->Polygon.OffsetFactor, ctx->Polygon.OffsetUnits);
@@ -1949,13 +2070,13 @@ void r300ResetHwState(r300ContextPtr r300)
r300->hw.fpi[3].cmd[i] = FP_SELA(0,W,NO,FP_TMP(0),0,0);
}
#endif
-
- r300->hw.unk4BC0.cmd[1] = 0;
-
- r300->hw.unk4BC8.cmd[1] = 0;
- r300->hw.unk4BC8.cmd[2] = 0;
- r300->hw.unk4BC8.cmd[3] = 0;
-
+ r300Enable(ctx, GL_FOG, ctx->Fog.Enabled);
+ ctx->Driver.Fogfv( ctx, GL_FOG_MODE, NULL );
+ ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+ ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+ ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, NULL );
r300->hw.at.cmd[R300_AT_UNKNOWN] = 0;
r300->hw.unk4BD8.cmd[1] = 0;
@@ -2128,6 +2249,7 @@ void r300InitStateFuncs(struct dd_function_table* functions)
functions->DepthFunc = r300DepthFunc;
functions->DepthMask = r300DepthMask;
functions->CullFace = r300CullFace;
+ functions->Fogfv = r300Fogfv;
functions->FrontFace = r300FrontFace;
functions->ShadeModel = r300ShadeModel;
diff --git a/src/mesa/drivers/dri/r300/r300_texmem.c b/src/mesa/drivers/dri/r300/r300_texmem.c
index a9f64b47c4c..c1d01020cdb 100644
--- a/src/mesa/drivers/dri/r300/r300_texmem.c
+++ b/src/mesa/drivers/dri/r300/r300_texmem.c
@@ -130,6 +130,12 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa,
srcPitch = t->image[0][0].width * texFormat->TexelBytes;
dstPitch = t->image[0][0].width * texFormat->TexelBytes;
break;
+ case 8:
+ case 16:
+ blit_format = R200_CP_COLOR_FORMAT_CI8;
+ srcPitch = t->image[0][0].width * texFormat->TexelBytes;
+ dstPitch = t->image[0][0].width * texFormat->TexelBytes;
+ break;
default:
return;
}
@@ -144,6 +150,10 @@ static void r300UploadGARTClientSubImage(r300ContextPtr rmesa,
width = texImage->Width;
height = texImage->Height;
+ if (texFormat->TexelBytes > 4) {
+ width *= texFormat->TexelBytes;
+ }
+
r300EmitWait(rmesa, R300_WAIT_3D);
r300EmitBlit(rmesa, blit_format,
@@ -177,6 +187,10 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa,
case 4:
blit_format = R200_CP_COLOR_FORMAT_ARGB8888;
break;
+ case 8:
+ case 16:
+ blit_format = R200_CP_COLOR_FORMAT_CI8;
+ break;
default:
return;
}
@@ -189,6 +203,10 @@ static void r300UploadRectSubImage(r300ContextPtr rmesa,
height = texImage->Height;
dstPitch = t->pitch;
+ if (texFormat->TexelBytes > 4) {
+ width *= texFormat->TexelBytes;
+ }
+
if (rmesa->prefer_gart_client_texturing && texImage->IsClientData) {
/* In this case, could also use GART texturing. This is
* currently disabled, but has been tested & works.
diff --git a/src/mesa/drivers/dri/r300/r300_vertexprog.c b/src/mesa/drivers/dri/r300/r300_vertexprog.c
index f794c9aa67a..9e32cfcfef9 100644
--- a/src/mesa/drivers/dri/r300/r300_vertexprog.c
+++ b/src/mesa/drivers/dri/r300/r300_vertexprog.c
@@ -916,6 +916,16 @@ void r300_translate_vertex_shader(struct r300_vertex_program *vp)
fprintf(stderr, "Dont know how to handle op %d yet\n", vpi->Opcode);
exit(-1);
break;
+ case OPCODE_SWZ:
+ hw_op=(src[0].File == PROGRAM_TEMPORARY) ? R300_VPI_OUT_OP_MAD_2 : R300_VPI_OUT_OP_MAD;
+
+ o_inst->op=MAKE_VSF_OP(hw_op, t_dst_index(vp, &vpi->DstReg),
+ t_dst_mask(vpi->DstReg.WriteMask), t_dst_class(vpi->DstReg.File));
+ o_inst->src1=t_src(vp, &src[0]);
+ o_inst->src2=ONE_SRC_0;
+ o_inst->src3=ZERO_SRC_0;
+
+ goto next;
case OPCODE_END:
break;
default:
diff --git a/src/mesa/drivers/dri/r300/radeon_context.c b/src/mesa/drivers/dri/r300/radeon_context.c
index 4e351dd66b0..0147c6492e5 100644
--- a/src/mesa/drivers/dri/r300/radeon_context.c
+++ b/src/mesa/drivers/dri/r300/radeon_context.c
@@ -76,7 +76,7 @@ static const GLubyte *radeonGetString(GLcontext * ctx, GLenum name)
case GL_RENDERER:
{
unsigned offset;
- GLuint agp_mode = radeon->radeonScreen->IsPCI ? 0 :
+ GLuint agp_mode = (radeon->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
radeon->radeonScreen->AGPMode;
const char* chipname;
diff --git a/src/mesa/drivers/dri/r300/radeon_span.c b/src/mesa/drivers/dri/r300/radeon_span.c
index 1f000b97666..1b74f6779b4 100644
--- a/src/mesa/drivers/dri/r300/radeon_span.c
+++ b/src/mesa/drivers/dri/r300/radeon_span.c
@@ -40,7 +40,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* Keith Whitwell <[email protected]>
*
*/
-
+#include <unistd.h>
#include "glheader.h"
#include "imports.h"
#include "swrast/swrast.h"
@@ -252,6 +252,29 @@ do { \
static void radeonSpanRenderStart( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ {
+ static int first = 1;
+ r300ContextPtr r300 = (r300ContextPtr)rmesa;
+
+ if (first) {
+ r300->span_dlocking = getenv("R300_SPAN_DISABLE_LOCKING") ? 1 : 0;
+ if (r300->span_dlocking == 0) {
+ fprintf(stderr, "Try R300_SPAN_DISABLE_LOCKING env var if this hangs.\n");
+ fflush(stderr);
+ sleep(1);
+ }
+ first = 0;
+ }
+
+ if (r300->span_dlocking) {
+ r300Flush(ctx);
+ LOCK_HARDWARE( rmesa );
+ radeonWaitForIdleLocked( rmesa );
+ UNLOCK_HARDWARE( rmesa );
+
+ return;
+ }
+ }
// R300_FIREVERTICES( rmesa );
// old code has flush
r300Flush(ctx);
@@ -262,8 +285,10 @@ static void radeonSpanRenderStart( GLcontext *ctx )
static void radeonSpanRenderFinish( GLcontext *ctx )
{
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+ r300ContextPtr r300 = (r300ContextPtr)rmesa;
_swrast_flush( ctx );
- UNLOCK_HARDWARE( rmesa );
+ if (r300->span_dlocking == 0)
+ UNLOCK_HARDWARE( rmesa );
}
void radeonInitSpanFuncs( GLcontext *ctx )
diff --git a/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
index 5ea9bb4eb45..1044973b001 100644
--- a/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
+++ b/src/mesa/drivers/dri/r300/radeon_vtxfmt_a.c
@@ -71,7 +71,7 @@ void radeon_vb_to_rvb(r300ContextPtr rmesa, struct radeon_vertex_buffer *rvb, st
CONV_VB(VERT_ATTRIB_COLOR1, SecondaryColorPtr[0]);
CONV_VB(VERT_ATTRIB_FOG, FogCoordPtr);
- for (i=0; i < MAX_TEXTURE_COORD_UNITS; i++)
+ for (i=0; i < ctx->Const.MaxTextureCoordUnits; i++)
CONV_VB(VERT_ATTRIB_TEX0 + i, TexCoordPtr[i]);
rvb->Primitive = vb->Primitive;
@@ -182,7 +182,7 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
unsigned int min = ~0, max = 0;
struct tnl_prim prim;
static void *ptr = NULL;
- static struct r300_dma_region rvb;
+ struct r300_dma_region rvb;
const GLvoid *indices = c_indices;
if (count > 65535) {
@@ -205,8 +205,8 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
return;
FLUSH_CURRENT( ctx, 0 );
- r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
+ memset(&rvb, 0, sizeof(rvb));
switch (type) {
case GL_UNSIGNED_BYTE:
for (i=0; i < count; i++) {
@@ -216,14 +216,22 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
max = ((unsigned char *)indices)[i];
}
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
elt_size = 2;
-
+#endif
r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
+#ifdef FORCE_32BITS_ELTS
+ for (i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
+#else
for (i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
+#endif
break;
case GL_UNSIGNED_SHORT:
@@ -234,14 +242,23 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
max = ((unsigned short int *)indices)[i];
}
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
elt_size = 2;
+#endif
r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
+#ifdef FORCE_32BITS_ELTS
+ for (i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
+#else
for (i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
+#endif
break;
case GL_UNSIGNED_INT:
@@ -252,17 +269,20 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
max = ((unsigned int *)indices)[i];
}
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
if (max - min <= 65535)
elt_size = 2;
else
elt_size = 4;
-
+#endif
r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
- if (max - min <= 65535)
+ if (elt_size == 2)
for (i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
else
@@ -278,12 +298,12 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
if (ctx->NewState)
_mesa_update_state( ctx );
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i];
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i];
}
r300UpdateShaders(rmesa);
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i];
}
@@ -311,8 +331,10 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
return;
}
} else {
- if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL)
+ if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) {
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
goto fallback;
+ }
rmesa->state.VB.Count = max - min + 1;
}
@@ -337,6 +359,7 @@ static void radeonDrawElements( GLenum mode, GLsizei count, GLenum type, const G
if(rvb.buf)
radeon_mm_use(rmesa, rvb.buf->id);
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
return;
fallback:
@@ -355,7 +378,7 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
int elt_size;
int i;
void *ptr = NULL;
- static struct r300_dma_region rvb;
+ struct r300_dma_region rvb;
const GLvoid *indices = c_indices;
if (count > 65535) {
@@ -381,23 +404,34 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
#ifdef OPTIMIZE_ELTS
min = 0;
#endif
- r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
- switch(type){
+ memset(&rvb, 0, sizeof(rvb));
+ switch (type){
case GL_UNSIGNED_BYTE:
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
elt_size = 2;
-
+#endif
r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
+#ifdef FORCE_32BITS_ELTS
+ for(i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
+#else
for(i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned char *)indices)[i] - min;
+#endif
break;
case GL_UNSIGNED_SHORT:
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
elt_size = 2;
-
+#endif
#ifdef OPTIMIZE_ELTS
if (min == 0 && ctx->Array.ElementArrayBufferObj->Name){
ptr = indices;
@@ -408,21 +442,29 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
+#ifdef FORCE_32BITS_ELTS
+ for(i=0; i < count; i++)
+ ((unsigned int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
+#else
for(i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned short int *)indices)[i] - min;
+#endif
break;
case GL_UNSIGNED_INT:
+#ifdef FORCE_32BITS_ELTS
+ elt_size = 4;
+#else
if (max - min <= 65535)
elt_size = 2;
else
elt_size = 4;
-
+#endif
r300AllocDmaRegion(rmesa, &rvb, count * elt_size, elt_size);
rvb.aos_offset = GET_START(&rvb);
ptr = rvb.address + rvb.start;
- if (max - min <= 65535)
+ if (elt_size == 2)
for (i=0; i < count; i++)
((unsigned short int *)ptr)[i] = ((unsigned int *)indices)[i] - min;
else
@@ -440,12 +482,12 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
if (ctx->NewState)
_mesa_update_state( ctx );
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i];
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i];
}
r300UpdateShaders(rmesa);
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i];
}
@@ -473,8 +515,10 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
return;
}*/
} else {
- if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL)
+ if (setup_arrays(rmesa, min) >= R300_FALLBACK_TCL) {
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
goto fallback;
+ }
rmesa->state.VB.Count = max - min + 1;
}
@@ -501,6 +545,7 @@ static void radeonDrawRangeElements(GLenum mode, GLuint min, GLuint max, GLsizei
if(rvb.buf)
radeon_mm_use(rmesa, rvb.buf->id);
+ r300ReleaseDmaRegion(rmesa, &rvb, __FUNCTION__);
return ;
fallback:
@@ -533,12 +578,12 @@ static void radeonDrawArrays( GLenum mode, GLint start, GLsizei count )
/* XXX: setup_arrays before state update? */
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
rmesa->temp_attrib[i] = TNL_CONTEXT(ctx)->vb.AttribPtr[i];
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = &rmesa->dummy_attrib[i];
}
r300UpdateShaders(rmesa);
- for (i=_TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) {
+ for (i=_TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
TNL_CONTEXT(ctx)->vb.AttribPtr[i] = rmesa->temp_attrib[i];
}
diff --git a/src/mesa/drivers/dri/radeon/Makefile b/src/mesa/drivers/dri/radeon/Makefile
index 34dc58e2dc2..6e46620b397 100644
--- a/src/mesa/drivers/dri/radeon/Makefile
+++ b/src/mesa/drivers/dri/radeon/Makefile
@@ -32,7 +32,7 @@ C_SOURCES = \
$(COMMON_SOURCES) \
$(DRIVER_SOURCES)
-DEFINES += -DRADEON_COMMON=0
+DRIVER_DEFINES = -DRADEON_COMMON=0
X86_SOURCES = \
radeon_vtxtmp_x86.S
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
index 791d1a37bc0..21161d2f69d 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.c
+++ b/src/mesa/drivers/dri/radeon/radeon_context.c
@@ -102,7 +102,7 @@ static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
static char buffer[128];
unsigned offset;
- GLuint agp_mode = rmesa->radeonScreen->IsPCI ? 0 :
+ GLuint agp_mode = (rmesa->radeonScreen->card_type==RADEON_CARD_PCI) ? 0 :
rmesa->radeonScreen->AGPMode;
switch ( name ) {
@@ -521,10 +521,6 @@ void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
radeonVtxfmtDestroy( rmesa->glCtx );
}
- /* free the Mesa context */
- rmesa->glCtx->DriverCtx = NULL;
- _mesa_destroy_context( rmesa->glCtx );
-
_mesa_vector4f_free( &rmesa->tcl.ObjClean );
if (rmesa->state.scissor.pClipRects) {
@@ -546,6 +542,10 @@ void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
assert( is_empty_list( & rmesa->swapped ) );
}
+ /* free the Mesa context */
+ rmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context( rmesa->glCtx );
+
/* free the option cache */
driDestroyOptionCache (&rmesa->optionCache);
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
index 9abd8667308..9902e60c595 100644
--- a/src/mesa/drivers/dri/radeon/radeon_context.h
+++ b/src/mesa/drivers/dri/radeon/radeon_context.h
@@ -735,7 +735,7 @@ struct radeon_context {
GLuint TclFallback;
GLuint Fallback;
GLuint NewGLState;
- GLuint tnl_index; /* index of bits for last tnl_install_attrs */
+ DECLARE_RENDERINPUTS(tnl_index_bitset); /* index of bits for last tnl_install_attrs */
/* Vertex buffers
*/
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
index 5257e541e5f..3a0a8d208b2 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.c
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.c
@@ -159,7 +159,7 @@ DRI_CONF_BEGIN
DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
- DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(16, 2, 16)
+ DRI_CONF_MAX_TEXTURE_IMAGE_UNITS(8, 2, 8)
DRI_CONF_MAX_TEXTURE_COORD_UNITS(8, 2, 8)
DRI_CONF_COMMAND_BUFFER_SIZE(8, 8, 32)
DRI_CONF_SECTION_END
@@ -209,6 +209,19 @@ extern const struct dri_extension card_extensions[];
static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+static int
+radeonGetParam(int fd, int param, void *value)
+{
+ int ret;
+ drm_radeon_getparam_t gp;
+
+ gp.param = param;
+ gp.value = value;
+
+ ret = drmCommandWriteRead( fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp));
+ return ret;
+}
+
static __GLcontextModes *
radeonFillInModes( unsigned pixel_bits, unsigned depth_bits,
unsigned stencil_bits, GLboolean have_back_buffer )
@@ -326,52 +339,39 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
/* This is first since which regions we map depends on whether or
* not we are using a PCI card.
*/
- screen->IsPCI = dri_priv->IsPCI;
-
+ screen->card_type = (dri_priv->IsPCI ? RADEON_CARD_PCI : RADEON_CARD_AGP);
{
int ret;
- drm_radeon_getparam_t gp;
-
- gp.param = RADEON_PARAM_GART_BUFFER_OFFSET;
- gp.value = &screen->gart_buffer_offset;
-
- ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp));
+ ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BUFFER_OFFSET,
+ &screen->gart_buffer_offset);
+
if (ret) {
FREE( screen );
fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BUFFER_OFFSET): %d\n", ret);
return NULL;
}
- if (sPriv->drmMinor >= 6) {
- gp.param = RADEON_PARAM_GART_BASE;
- gp.value = &screen->gart_base;
-
- ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- FREE( screen );
- fprintf(stderr, "drmR200GetParam (RADEON_PARAM_GART_BASE): %d\n", ret);
- return NULL;
- }
-
- gp.param = RADEON_PARAM_IRQ_NR;
- gp.value = &screen->irq;
-
- ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
- &gp, sizeof(gp));
- if (ret) {
- FREE( screen );
- fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
- return NULL;
- }
- screen->drmSupportsCubeMapsR200 = (sPriv->drmMinor >= 7);
- screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11);
- screen->drmSupportsTriPerf = (sPriv->drmMinor >= 16);
- screen->drmSupportsFragShader = (sPriv->drmMinor >= 18);
- screen->drmSupportsPointSprites = (sPriv->drmMinor >= 13);
- screen->drmSupportsCubeMapsR100 = (sPriv->drmMinor >= 15);
+ ret = radeonGetParam( sPriv->fd, RADEON_PARAM_GART_BASE,
+ &screen->gart_base);
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_GART_BASE): %d\n", ret);
+ return NULL;
+ }
+
+ ret = radeonGetParam( sPriv->fd, RADEON_PARAM_IRQ_NR,
+ &screen->irq);
+ if (ret) {
+ FREE( screen );
+ fprintf(stderr, "drm_radeon_getparam_t (RADEON_PARAM_IRQ_NR): %d\n", ret);
+ return NULL;
}
+ screen->drmSupportsCubeMapsR200 = (sPriv->drmMinor >= 7);
+ screen->drmSupportsBlendColor = (sPriv->drmMinor >= 11);
+ screen->drmSupportsTriPerf = (sPriv->drmMinor >= 16);
+ screen->drmSupportsFragShader = (sPriv->drmMinor >= 18);
+ screen->drmSupportsPointSprites = (sPriv->drmMinor >= 13);
+ screen->drmSupportsCubeMapsR100 = (sPriv->drmMinor >= 15);
}
screen->mmio.handle = dri_priv->registerHandle;
@@ -425,9 +425,7 @@ radeonCreateScreen( __DRIscreenPrivate *sPriv )
return NULL;
}
- screen->gart_texture_offset = dri_priv->gartTexOffset + ( screen->IsPCI
- ? INREG( RADEON_AIC_LO_ADDR )
- : ( ( INREG( RADEON_MC_AGP_LOCATION ) & 0x0ffffU ) << 16 ) );
+ screen->gart_texture_offset = dri_priv->gartTexOffset + screen->gart_base;
}
screen->chip_flags = 0;
@@ -976,12 +974,12 @@ __driCreateNewScreen_20050727( __DRInativeDisplay *dpy,
static const char *driver_name = "Radeon";
static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
- static const __DRIversion drm_expected = { 1, 3, 0 };
+ static const __DRIversion drm_expected = { 1, 6, 0 };
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R200)
static const char *driver_name = "R200";
static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
- static const __DRIversion drm_expected = { 1, 5, 0 };
+ static const __DRIversion drm_expected = { 1, 6, 0 };
#elif RADEON_COMMON && defined(RADEON_COMMON_FOR_R300)
static const char *driver_name = "R300";
static const __DRIutilversion2 ddx_expected = { 4, 5, 0, 0 };
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
index 08433c445b8..3e0f9454e7f 100644
--- a/src/mesa/drivers/dri/radeon/radeon_screen.h
+++ b/src/mesa/drivers/dri/radeon/radeon_screen.h
@@ -59,7 +59,7 @@ typedef struct {
int chip_family;
int chip_flags;
int cpp;
- int IsPCI; /* Current card is a PCI card */
+ int card_type;
int AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
index 447619b56d0..307c1f341b4 100644
--- a/src/mesa/drivers/dri/radeon/radeon_state.c
+++ b/src/mesa/drivers/dri/radeon/radeon_state.c
@@ -1282,8 +1282,8 @@ radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
GLint ref, GLuint mask )
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
- GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
- (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
+ GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
+ ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
RADEON_STATECHANGE( rmesa, ctx );
RADEON_STATECHANGE( rmesa, msk );
@@ -1330,7 +1330,7 @@ radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
RADEON_STATECHANGE( rmesa, msk );
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
- (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT);
+ ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT);
}
static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
@@ -1458,9 +1458,9 @@ static void radeonClearStencil( GLcontext *ctx, GLint s )
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
rmesa->state.stencil.clear =
- ((GLuint) ctx->Stencil.Clear |
+ ((GLuint) (ctx->Stencil.Clear & 0xff) |
(0xff << RADEON_STENCIL_MASK_SHIFT) |
- (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
+ ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
index 9924931e1a2..4d5bbbd1f18 100644
--- a/src/mesa/drivers/dri/radeon/radeon_swtcl.c
+++ b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
@@ -92,10 +92,11 @@ static void radeonSetVertexFormat( GLcontext *ctx )
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
int fmt_0 = 0;
int offset = 0;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
/* Important:
*/
@@ -113,7 +114,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
* build up a hardware vertex.
*/
if ( !rmesa->swtcl.needproj ||
- (index & _TNL_BITS_TEX_ANY)) { /* for projtex */
+ RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* for projtex */
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F,
RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z | RADEON_CP_VC_FRMT_W0 );
offset = 4;
@@ -135,10 +136,11 @@ static void radeonSetVertexFormat( GLcontext *ctx )
offset += 1;
rmesa->swtcl.specoffset = 0;
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
#if MESA_LITTLE_ENDIAN
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->swtcl.specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
RADEON_CP_VC_FRMT_PKSPEC );
@@ -147,7 +149,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
EMIT_PAD( 3 );
}
- if (index & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F,
RADEON_CP_VC_FRMT_PKSPEC );
}
@@ -155,7 +157,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
EMIT_PAD( 1 );
}
#else
- if (index & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F,
RADEON_CP_VC_FRMT_PKSPEC );
}
@@ -163,7 +165,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
EMIT_PAD( 1 );
}
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
rmesa->swtcl.specoffset = offset;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR,
RADEON_CP_VC_FRMT_PKSPEC );
@@ -174,11 +176,11 @@ static void radeonSetVertexFormat( GLcontext *ctx )
#endif
}
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
int i;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- if (index & _TNL_BIT_TEX(i)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
GLuint sz = VB->TexCoordPtr[i]->size;
switch (sz) {
@@ -204,7 +206,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
}
}
- if ( rmesa->tnl_index != index ||
+ if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
fmt_0 != rmesa->swtcl.vertex_format) {
RADEON_NEWPRIM(rmesa);
rmesa->swtcl.vertex_format = fmt_0;
@@ -214,7 +216,7 @@ static void radeonSetVertexFormat( GLcontext *ctx )
rmesa->swtcl.vertex_attr_count,
NULL, 0 );
rmesa->swtcl.vertex_size /= 4;
- rmesa->tnl_index = index;
+ RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
if (RADEON_DEBUG & DEBUG_VERTS)
fprintf( stderr, "%s: vertex_size= %d floats\n",
__FUNCTION__, rmesa->swtcl.vertex_size);
@@ -257,8 +259,9 @@ void radeonChooseVertexState( GLcontext *ctx )
* bigger one.
*/
- if ( ((tnl->render_inputs & (_TNL_BITS_TEX_ANY|_TNL_BIT_COLOR1) ) == 0)
- || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ if ((!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) &&
+ !RENDERINPUTS_TEST( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ))
+ || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
rmesa->swtcl.needproj = GL_TRUE;
se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
RADEON_VTX_Z_PRE_MULT_1_OVER_W0 |
@@ -938,7 +941,7 @@ void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
*/
_tnl_invalidate_vertex_state( ctx, ~0 );
_tnl_invalidate_vertices( ctx, ~0 );
- rmesa->tnl_index = 0;
+ RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
radeonChooseVertexState( ctx );
radeonChooseRenderState( ctx );
}
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
index 3b3f459dffb..e9a76dc92eb 100644
--- a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
@@ -929,7 +929,8 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
- MEMSET( vfmt, 0, sizeof(GLvertexformat) );
+ /* start by initializing to no-op functions */
+ _mesa_noop_vtxfmt_init(vfmt);
/* Hook in chooser functions for codegen, etc:
*/
@@ -939,7 +940,6 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
*/
vfmt->Materialfv = radeon_Materialfv;
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
- vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
vfmt->Begin = radeon_Begin;
vfmt->End = radeon_End;
@@ -953,15 +953,6 @@ void radeonVtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
vfmt->DrawElements = radeon_fallback_DrawElements;
vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements;
-
- /* Not active in supported states; just keep ctx->Current uptodate:
- */
- vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
- vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
- vfmt->Indexf = _mesa_noop_Indexf;
- vfmt->Indexfv = _mesa_noop_Indexfv;
-
-
/* Active but unsupported -- fallback if we receive these:
*/
vfmt->CallList = radeon_fallback_CallList;
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S b/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S
index d2bb1d15192..1b433491aa8 100644
--- a/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S
+++ b/src/mesa/drivers/dri/radeon/radeon_vtxtmp_x86.S
@@ -492,3 +492,7 @@ GLOBL( _sse_MultiTexCoord2f_2 )
ret
GLOBL( _sse_MultiTexCoord2f_2_end )
#endif
+
+#if defined (__ELF__) && defined (__linux__)
+ .section .note.GNU-stack,"",%progbits
+#endif
diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c
index 7f83d868cb8..7ead588dac8 100644
--- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c
+++ b/src/mesa/drivers/dri/radeon/server/radeon_dri.c
@@ -1260,6 +1260,7 @@ static int radeonInitFBDev( DRIDriverContext *ctx )
}
ctx->shared.virtualWidth = dummy;
+ ctx->shared.Width = dummy;
}
fprintf(stderr,"shared virtual width is %d\n", ctx->shared.virtualWidth);
diff --git a/src/mesa/drivers/dri/savage/savagestate.c b/src/mesa/drivers/dri/savage/savagestate.c
index 44cf2f20d37..3a267e025c9 100644
--- a/src/mesa/drivers/dri/savage/savagestate.c
+++ b/src/mesa/drivers/dri/savage/savagestate.c
@@ -986,8 +986,8 @@ savageDDStencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
const u_int32_t zBufCtrl = imesa->regs.s4.zBufCtrl.ui;
const u_int32_t stencilCtrl = imesa->regs.s4.stencilCtrl.ui;
- imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0];
- imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0];
+ imesa->regs.s4.zBufCtrl.ni.stencilRefVal = ctx->Stencil.Ref[0] & 0xff;
+ imesa->regs.s4.stencilCtrl.ni.readMask = ctx->Stencil.ValueMask[0] & 0xff;
switch (ctx->Stencil.Function[0])
{
@@ -1015,8 +1015,8 @@ savageDDStencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
- if (imesa->regs.s4.stencilCtrl.ni.writeMask != ctx->Stencil.WriteMask[0]) {
- imesa->regs.s4.stencilCtrl.ni.writeMask = ctx->Stencil.WriteMask[0];
+ if (imesa->regs.s4.stencilCtrl.ni.writeMask != (ctx->Stencil.WriteMask[0] & 0xff)) {
+ imesa->regs.s4.stencilCtrl.ni.writeMask = (ctx->Stencil.WriteMask[0] & 0xff);
imesa->dirty |= SAVAGE_UPLOAD_GLOBAL;
}
}
diff --git a/src/mesa/drivers/dri/savage/savagetex.c b/src/mesa/drivers/dri/savage/savagetex.c
index b2802904bda..f0fe0c52594 100644
--- a/src/mesa/drivers/dri/savage/savagetex.c
+++ b/src/mesa/drivers/dri/savage/savagetex.c
@@ -525,80 +525,11 @@ savageAllocTexObj( struct gl_texture_object *texObj )
* because we can't tell the hardware to ignore the color components
* and only use the alpha component. So we define our own texture
* formats that promote to ARGB8888 or ARGB4444 and set the color
- * components to white. This way we get the correct result. */
-static GLboolean
-_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
- GLenum baseInternalFormat,
- const struct gl_texture_format *dstFormat,
- GLvoid *dstAddr,
- GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
- GLint dstRowStride, GLint dstImageStride,
- GLint srcWidth, GLint srcHeight, GLint srcDepth,
- GLenum srcFormat, GLenum srcType,
- const GLvoid *srcAddr,
- const struct gl_pixelstore_attrib *srcPacking);
-static GLboolean
-_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
- GLenum baseInternalFormat,
- const struct gl_texture_format *dstFormat,
- GLvoid *dstAddr,
- GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
- GLint dstRowStride, GLint dstImageStride,
- GLint srcWidth, GLint srcHeight, GLint srcDepth,
- GLenum srcFormat, GLenum srcType,
- const GLvoid *srcAddr,
- const struct gl_pixelstore_attrib *srcPacking);
-
-static struct gl_texture_format _savage_texformat_a1114444 = {
- MESA_FORMAT_ARGB4444, /* MesaFormat */
- GL_RGBA, /* BaseFormat */
- GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
- 4, /* RedBits */
- 4, /* GreenBits */
- 4, /* BlueBits */
- 4, /* AlphaBits */
- 0, /* LuminanceBits */
- 0, /* IntensityBits */
- 0, /* IndexBits */
- 0, /* DepthBits */
- 0, /* StencilBits */
- 2, /* TexelBytes */
- _savage_texstore_a1114444, /* StoreTexImageFunc */
- NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
- * savageDDInitTextureFuncs */
-};
-static struct gl_texture_format _savage_texformat_a1118888 = {
- MESA_FORMAT_ARGB8888, /* MesaFormat */
- GL_RGBA, /* BaseFormat */
- GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
- 8, /* RedBits */
- 8, /* GreenBits */
- 8, /* BlueBits */
- 8, /* AlphaBits */
- 0, /* LuminanceBits */
- 0, /* IntensityBits */
- 0, /* IndexBits */
- 0, /* DepthBits */
- 0, /* StencilBits */
- 4, /* TexelBytes */
- _savage_texstore_a1118888, /* StoreTexImageFunc */
- NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
- * savageDDInitTextureFuncs */
-};
-
+ * components to white. This way we get the correct result.
+ */
static GLboolean
-_savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
- GLenum baseInternalFormat,
- const struct gl_texture_format *dstFormat,
- GLvoid *dstAddr,
- GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
- GLint dstRowStride, GLint dstImageStride,
- GLint srcWidth, GLint srcHeight, GLint srcDepth,
- GLenum srcFormat, GLenum srcType,
- const GLvoid *srcAddr,
- const struct gl_pixelstore_attrib *srcPacking)
+_savage_texstore_a1114444(TEXSTORE_PARAMS)
{
- /* general path */
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
baseInternalFormat,
baseInternalFormat,
@@ -606,10 +537,6 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
srcFormat, srcType, srcAddr,
srcPacking);
const GLchan *src = tempImage;
- GLubyte *dstImage = (GLubyte *) dstAddr
- + dstZoffset * dstImageStride
- + dstYoffset * dstRowStride
- + dstXoffset * dstFormat->TexelBytes;
GLint img, row, col;
ASSERT(dstFormat == &_savage_texformat_a1114444);
@@ -619,7 +546,10 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
return GL_FALSE;
_mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
for (img = 0; img < srcDepth; img++) {
- GLubyte *dstRow = dstImage;
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
for (row = 0; row < srcHeight; row++) {
GLushort *dstUI = (GLushort *) dstRow;
for (col = 0; col < srcWidth; col++) {
@@ -629,25 +559,16 @@ _savage_texstore_a1114444 (GLcontext *ctx, GLuint dims,
}
dstRow += dstRowStride;
}
- dstImage += dstImageStride;
}
_mesa_free((void *) tempImage);
return GL_TRUE;
}
+
+
static GLboolean
-_savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
- GLenum baseInternalFormat,
- const struct gl_texture_format *dstFormat,
- GLvoid *dstAddr,
- GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
- GLint dstRowStride, GLint dstImageStride,
- GLint srcWidth, GLint srcHeight, GLint srcDepth,
- GLenum srcFormat, GLenum srcType,
- const GLvoid *srcAddr,
- const struct gl_pixelstore_attrib *srcPacking)
+_savage_texstore_a1118888(TEXSTORE_PARAMS)
{
- /* general path */
const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
baseInternalFormat,
baseInternalFormat,
@@ -655,10 +576,6 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
srcFormat, srcType, srcAddr,
srcPacking);
const GLchan *src = tempImage;
- GLubyte *dstImage = (GLubyte *) dstAddr
- + dstZoffset * dstImageStride
- + dstYoffset * dstRowStride
- + dstXoffset * dstFormat->TexelBytes;
GLint img, row, col;
ASSERT(dstFormat == &_savage_texformat_a1118888);
@@ -668,7 +585,10 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
return GL_FALSE;
_mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
for (img = 0; img < srcDepth; img++) {
- GLubyte *dstRow = dstImage;
+ GLubyte *dstRow = (GLubyte *) dstAddr
+ + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes
+ + dstYoffset * dstRowStride
+ + dstXoffset * dstFormat->TexelBytes;
for (row = 0; row < srcHeight; row++) {
GLuint *dstUI = (GLuint *) dstRow;
for (col = 0; col < srcWidth; col++) {
@@ -678,13 +598,51 @@ _savage_texstore_a1118888 (GLcontext *ctx, GLuint dims,
}
dstRow += dstRowStride;
}
- dstImage += dstImageStride;
}
_mesa_free((void *) tempImage);
return GL_TRUE;
}
+
+static struct gl_texture_format _savage_texformat_a1114444 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 4, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 2, /* TexelBytes */
+ _savage_texstore_a1114444, /* StoreTexImageFunc */
+ NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
+ * savageDDInitTextureFuncs */
+};
+static struct gl_texture_format _savage_texformat_a1118888 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 8, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 0, /* StencilBits */
+ 4, /* TexelBytes */
+ _savage_texstore_a1118888, /* StoreTexImageFunc */
+ NULL, NULL, NULL, NULL, NULL, NULL /* FetchTexel* filled in by
+ * savageDDInitTextureFuncs */
+};
+
+
/* Called by the _mesa_store_teximage[123]d() functions. */
static const struct gl_texture_format *
savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
diff --git a/src/mesa/drivers/dri/savage/savagetris.c b/src/mesa/drivers/dri/savage/savagetris.c
index 18470401372..3dd821a4d39 100644
--- a/src/mesa/drivers/dri/savage/savagetris.c
+++ b/src/mesa/drivers/dri/savage/savagetris.c
@@ -867,15 +867,17 @@ static GLboolean savageCheckPTexHack( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
- if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) {
- if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) {
+ if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
return GL_TRUE; /* apply ptex hack */
else
FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
}
- if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4)
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4)
FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
return GL_FALSE; /* don't apply ptex hack */
@@ -929,10 +931,11 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint setupIndex = SAVAGE_EMIT_XYZ;
GLubyte skip;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
imesa->vertex_attr_count = 0;
skip = SAVAGE_SKIP_ALL_S3D;
@@ -941,7 +944,7 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
- if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE))
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
else {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
@@ -952,17 +955,17 @@ static __inline__ GLuint savageChooseVertexFormat_s3d( GLcontext *ctx )
/* t_context.c always includes a diffuse color */
EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
- if ((index & _TNL_BIT_COLOR1))
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
else
EMIT_PAD( 3 );
- if ((index & _TNL_BIT_FOG))
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
else
EMIT_PAD( 1 );
skip &= ~SAVAGE_SKIP_C1;
- if (index & _TNL_BIT_TEX(0)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
if (imesa->ptexHack)
EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
else if (VB->TexCoordPtr[0]->size == 4)
@@ -991,28 +994,27 @@ static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx )
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint setupIndex = SAVAGE_EMIT_XYZ;
GLubyte skip;
GLuint size, mask;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
skip = SAVAGE_SKIP_ALL_S4;
skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
- if ((index & _TNL_BITS_TEX_ANY) || !(ctx->_TriangleCaps & DD_FLATSHADE))
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
NEED_ATTR( SAVAGE_EMIT_W, SAVAGE_SKIP_W );
/* t_context.c always includes a diffuse color */
NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
-
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
- if ((index & _TNL_BIT_COLOR1))
- NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
- if ((index & _TNL_BIT_FOG))
- NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
- }
- if (index & _TNL_BIT_TEX(0)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
+ NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
+ NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
if (imesa->ptexHack)
NEED_ATTR( SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
else if (VB->TexCoordPtr[0]->size == 4)
@@ -1024,7 +1026,7 @@ static __inline__ GLuint savageChooseVertexFormat_s4( GLcontext *ctx )
else
NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
}
- if (index & _TNL_BIT_TEX(1)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
if (VB->TexCoordPtr[1]->size == 4)
/* projective textures are not supported by the hardware */
assert (0); /* should be caught by savageCheckPTexHack */
diff --git a/src/mesa/drivers/dri/sis/sis_clear.c b/src/mesa/drivers/dri/sis/sis_clear.c
index d7807b157e9..637d502381e 100644
--- a/src/mesa/drivers/dri/sis/sis_clear.c
+++ b/src/mesa/drivers/dri/sis/sis_clear.c
@@ -133,7 +133,8 @@ sisDDClear( GLcontext * ctx, GLbitfield mask, GLboolean all,
if ((smesa->current.hwCapEnable2 & (MASK_AlphaMaskWriteEnable |
MASK_ColorMaskWriteEnable) &&
(mask & (BUFFER_BIT_BACK_LEFT | BUFFER_BIT_FRONT_LEFT)) != 0) ||
- (ctx->Stencil.WriteMask[0] < 0xff && (mask & BUFFER_BIT_STENCIL) != 0) )
+ ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff &&
+ (mask & BUFFER_BIT_STENCIL) != 0) )
{
mask = sis_3D_Clear( ctx, mask, x1, y1, width1, height1 );
}
@@ -213,13 +214,13 @@ sis_3D_Clear( GLcontext * ctx, GLbitfield mask,
if (bClrStencil) {
dwSten1 = STENCIL_FORMAT_8 | SiS_STENCIL_ALWAYS |
- (ctx->Stencil.Clear << 8) | 0xff;
+ ((ctx->Stencil.Clear & 0xff) << 8) | 0xff;
dwSten2 = SiS_SFAIL_REPLACE | SiS_SPASS_ZFAIL_REPLACE |
SiS_SPASS_ZPASS_REPLACE;
dwEnable1 = MASK_ZWriteEnable | MASK_StencilWriteEnable |
MASK_StencilTestEnable;
dwEnable2 |= MASK_ZMaskWriteEnable;
- dwDepthMask |= ctx->Stencil.WriteMask[0] << 24;
+ dwDepthMask |= (ctx->Stencil.WriteMask[0] & 0xff) << 24;
} else if (bClrDepth) {
dwEnable1 = MASK_ZWriteEnable;
dwEnable2 |= MASK_ZMaskWriteEnable;
diff --git a/src/mesa/drivers/dri/sis/sis_context.h b/src/mesa/drivers/dri/sis/sis_context.h
index ead4a26678e..c349bf96ed2 100644
--- a/src/mesa/drivers/dri/sis/sis_context.h
+++ b/src/mesa/drivers/dri/sis/sis_context.h
@@ -332,7 +332,7 @@ struct sis_context
GLint drawableID;
GLint GlobalFlag;
- GLuint last_tcl_state;
+ DECLARE_RENDERINPUTS(last_tcl_state_bitset);
/* Stereo */
GLboolean useStereo;
diff --git a/src/mesa/drivers/dri/sis/sis_state.c b/src/mesa/drivers/dri/sis/sis_state.c
index 1a4c3241153..a30001c7462 100644
--- a/src/mesa/drivers/dri/sis/sis_state.c
+++ b/src/mesa/drivers/dri/sis/sis_state.c
@@ -251,7 +251,7 @@ sisDDDepthMask( GLcontext * ctx, GLboolean flag )
if (ctx->Visual.stencilBits) {
if (flag || (ctx->Stencil.WriteMask[0] != 0)) {
current->hwCapEnable |= MASK_ZWriteEnable;
- if (flag && (ctx->Stencil.WriteMask[0] == 0xff)) {
+ if (flag && ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff)) {
current->hwCapEnable2 &= ~MASK_ZMaskWriteEnable;
} else {
current->hwCapEnable2 |= MASK_ZMaskWriteEnable;
diff --git a/src/mesa/drivers/dri/sis/sis_stencil.c b/src/mesa/drivers/dri/sis/sis_stencil.c
index 1febe86b94c..a1ce2966e89 100644
--- a/src/mesa/drivers/dri/sis/sis_stencil.c
+++ b/src/mesa/drivers/dri/sis/sis_stencil.c
@@ -45,8 +45,9 @@ sisDDStencilFuncSeparate( GLcontext * ctx, GLenum face,
__GLSiSHardware *current = &smesa->current;
/* set reference */
- current->hwStSetting = STENCIL_FORMAT_8 | (ctx->Stencil.Ref[0] << 8) |
- ctx->Stencil.ValueMask[0];
+ current->hwStSetting = (STENCIL_FORMAT_8 |
+ ((ctx->Stencil.Ref[0] & 0xff) << 8) |
+ (ctx->Stencil.ValueMask[0] & 0xff));
switch (func)
{
diff --git a/src/mesa/drivers/dri/sis/sis_tris.c b/src/mesa/drivers/dri/sis/sis_tris.c
index 24f6cb9aa87..a0e39dcd3c9 100644
--- a/src/mesa/drivers/dri/sis/sis_tris.c
+++ b/src/mesa/drivers/dri/sis/sis_tris.c
@@ -842,10 +842,12 @@ static void sisRenderStart( GLcontext *ctx )
TNLcontext *tnl = TNL_CONTEXT(ctx);
sisContextPtr smesa = SIS_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint AGPParseSet = smesa->AGPParseSet;
GLboolean tex_fallback = GL_FALSE;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
if (ctx->DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT &&
smesa->driDrawable->numClipRects != 0)
{
@@ -869,7 +871,7 @@ static void sisRenderStart( GLcontext *ctx )
AGPParseSet &= ~(MASK_VertexDWSize | MASK_VertexDataFormat);
AGPParseSet |= SiS_PS_HAS_XYZ | SiS_PS_HAS_DIFFUSE;
- if (index & _TNL_BITS_TEX_ANY) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
EMIT_ATTR(_TNL_ATTRIB_POS, EMIT_4F_VIEWPORT);
AGPParseSet |= SiS_PS_HAS_W;
smesa->coloroffset = 4;
@@ -881,17 +883,18 @@ static void sisRenderStart( GLcontext *ctx )
EMIT_ATTR(_TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA);
smesa->specoffset = 0;
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
AGPParseSet |= SiS_PS_HAS_SPECULAR;
- if (index & _TNL_BIT_COLOR1) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
EMIT_ATTR(_TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR);
smesa->specoffset = smesa->coloroffset + 1;
} else {
EMIT_PAD(3);
}
- if (index & _TNL_BIT_FOG) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR(_TNL_ATTRIB_FOG, EMIT_1UB_1F);
} else {
EMIT_PAD(1);
@@ -899,14 +902,14 @@ static void sisRenderStart( GLcontext *ctx )
}
/* projective textures are not supported by the hardware */
- if (index & _TNL_BIT_TEX(0)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
if (VB->TexCoordPtr[0]->size > 2)
tex_fallback = GL_TRUE;
EMIT_ATTR(_TNL_ATTRIB_TEX0, EMIT_2F);
AGPParseSet |= SiS_PS_HAS_UV0;
}
/* Will only hit tex1 on SiS300 */
- if (index & _TNL_BIT_TEX(1)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
if (VB->TexCoordPtr[1]->size > 2)
tex_fallback = GL_TRUE;
EMIT_ATTR(_TNL_ATTRIB_TEX1, EMIT_2F);
@@ -914,7 +917,7 @@ static void sisRenderStart( GLcontext *ctx )
}
FALLBACK(smesa, SIS_FALLBACK_TEXTURE, tex_fallback);
- if (smesa->last_tcl_state != index) {
+ if (!RENDERINPUTS_EQUAL( smesa->last_tcl_state_bitset, index_bitset )) {
smesa->AGPParseSet = AGPParseSet;
smesa->vertex_size = _tnl_install_attrs( ctx, smesa->vertex_attrs,
diff --git a/src/mesa/drivers/dri/tdfx/BUGS b/src/mesa/drivers/dri/tdfx/BUGS
new file mode 100644
index 00000000000..b15f6a91ed8
--- /dev/null
+++ b/src/mesa/drivers/dri/tdfx/BUGS
@@ -0,0 +1,64 @@
+REMOVE THIS FILE BEFORE MERGING WITH TRUNK
+------------------------------------------
+
+OUTSTANDING BUGS
+
+demos/reflect - reading back Z on Voodoo3, image offset to right
+ Fixed in latest Glide.
+
+Q3 - some polygons drawn as vertical strips, similar to bug that was
+ seen in demos/fire. Voodoo3 only. May be related to glDepthMask
+ or glColorMask.
+
+book/fog - not fogging
+ Fog in orthograph mode still not implemented. Checking with
+ 3dfx engineers for ideas.
+
+Q3 demo crashes after changing display settings
+ but the full Q3 game version seems OK.
+
+
+
+MORE OUTSTANDING BUGS
+
+private context was NULL! causing immediate failure of any glx prog. cant
+reproduce after restarting the X server. putting it down as halluc.
+
+texture object image was NULL, causing segmentation failure. happens with
+prboom. ive put a check in tdfx_texstate.c but this isn't a fix.
+
+prboom, wall textures near first chainsaw aren't bound properly. sideways
+movements causes the wall textures to move with you. prboom busted?
+
+16bpp mode, quake3, windowed, q3dm1, floor under rocketlauncher bands. it
+looks like multitexturing gone wrong. i'll disable a tmu and test.
+
+sof, polygons appear at wrong x,y,z positions, intermittent, have not yet
+found reliable way of reproducing. culling? sometimes polys disappear.
+
+descent3 is all black in 16bpp mode - FIXED (palette problems)
+
+smeared pixels in quake3 - FIXED (texture memory overlapped FB)
+
+
+
+PERFORMANCE COMPARISON (Brian / Alan)
+
+ V3/16 is Voodoo3 in 16bpp on a P3/500
+ V5/16 is Voodoo5 in 16bpp on a P3/600
+ V5/32 is Voodoo5 in 32bpp on a P3/600
+ V5A/16 is Voodoo5 in 16bpp on an Alpha AXP/600
+ V5A/32 is Voodoo5 in 32bpp on an Alpha AXP/600
+
+ tdfx-2-1-branch tdfx-3-0-0-branch
+demo V3/16 V5/16 V5/32 V3/16 V5/16 V5/32 V5A/16 V5A/32
+------------------------------------------------------------------------
+gloss 257 183 174 320 308 177 313 167
+fire 42 39 52 41
+fire (no help) 98 80 50 106 113 73 124 80
+tunnel 61 50 70 58
+tunnel (no help) 167 142 57 138 152 113 171 122
+gears 663 554 540 881 1232 776 1484 830
+teapot 20 21 37 36
+teapot (no help) 22 14 14 24 30 30 43 42
+
diff --git a/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S
new file mode 100644
index 00000000000..0f4cc45089b
--- /dev/null
+++ b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fastpath.S
@@ -0,0 +1,84 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fastpath.S,v 1.2 2000/09/26 15:56:51 tsi Exp $ */
+
+#include "../../X86/assyntax.h"
+
+#define SETUP_RGBA 0x1
+#define SETUP_TMU0 0x2
+#define SETUP_TMU1 0x4
+
+
+/* Pack either rgba or texture into the remaining half of a 32 byte vertex.
+ */
+#define CLIP_R 24
+#define CLIP_G 16
+#define CLIP_B 20
+#define CLIP_A 28 /* defined inf fxdrv.h */
+
+#define CLIP_S0 16
+#define CLIP_T0 20
+#define CLIP_S1 24
+#define CLIP_T1 28
+
+#define SIZE 4
+#define TYPE (0)
+#define TAG(x) x
+#include "fx_3dnow_fasttmp.h"
+
+#define SIZE 8
+#define TYPE (SETUP_RGBA)
+#define TAG(x) x##_RGBA
+#include "fx_3dnow_fasttmp.h"
+
+#define SIZE 6
+#define TYPE (SETUP_TMU0)
+#define TAG(x) x##_TMU0
+#include "fx_3dnow_fasttmp.h"
+
+#define SIZE 8
+#define TYPE (SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_TMU0_TMU1
+#include "fx_3dnow_fasttmp.h"
+
+#undef CLIP_S1
+#undef CLIP_T1
+#define CLIP_S1 16
+#define CLIP_T1 20
+
+#define SIZE 6
+#define TYPE (SETUP_TMU1)
+#define TAG(x) x##_TMU1
+#include "fx_3dnow_fasttmp.h"
+
+/* These three need to use a full 64 byte clip-space vertex.
+ */
+#undef CLIP_S0
+#undef CLIP_T0
+#undef CLIP_S1
+#undef CLIP_T1
+
+#define CLIP_S0 32
+#define CLIP_T0 36
+#define CLIP_S1 40
+#define CLIP_T1 44
+
+#define SIZE 10
+#define TYPE (SETUP_RGBA|SETUP_TMU0)
+#define TAG(x) x##_RGBA_TMU0
+#include "fx_3dnow_fasttmp.h"
+
+#define SIZE 12
+#define TYPE (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
+#define TAG(x) x##_RGBA_TMU0_TMU1
+#include "fx_3dnow_fasttmp.h"
+
+#undef CLIP_S1
+#undef CLIP_T1
+#define CLIP_S1 32
+#define CLIP_T1 36
+
+#define SIZE 10
+#define TYPE (SETUP_RGBA|SETUP_TMU1)
+#define TAG(x) x##_RGBA_TMU1
+#include "fx_3dnow_fasttmp.h"
+
+
diff --git a/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h
new file mode 100644
index 00000000000..9ec4935d781
--- /dev/null
+++ b/src/mesa/drivers/dri/tdfx/X86/fx_3dnow_fasttmp.h
@@ -0,0 +1,314 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/X86/fx_3dnow_fasttmp.h,v 1.2 2000/09/26 15:56:51 tsi Exp $ */
+
+#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER)
+#define TAGLLBL(a) TAG(.L##a)
+#else
+#define TAGLLBL(a) TAG(a)
+#endif
+
+#if !GLIDE3
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 4
+#define GR_VERTEX_Z_OFFSET 8
+#define GR_VERTEX_R_OFFSET 12
+#define GR_VERTEX_G_OFFSET 16
+#define GR_VERTEX_B_OFFSET 20
+#define GR_VERTEX_OOZ_OFFSET 24
+#define GR_VERTEX_A_OFFSET 28
+#define GR_VERTEX_OOW_OFFSET 32
+
+#else /* GLIDE3 */
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 4
+#define GR_VERTEX_OOZ_OFFSET 8
+#define GR_VERTEX_OOW_OFFSET 12
+#define GR_VERTEX_R_OFFSET 16
+#define GR_VERTEX_G_OFFSET 20
+#define GR_VERTEX_B_OFFSET 24
+#define GR_VERTEX_A_OFFSET 28
+#define GR_VERTEX_Z_OFFSET 32
+
+#endif /* GLIDE3 */
+
+#define GR_VERTEX_SOW_TMU0_OFFSET 36
+#define GR_VERTEX_TOW_TMU0_OFFSET 40
+#define GR_VERTEX_OOW_TMU0_OFFSET 44
+#define GR_VERTEX_SOW_TMU1_OFFSET 48
+#define GR_VERTEX_TOW_TMU1_OFFSET 52
+#define GR_VERTEX_OOW_TMU1_OFFSET 56
+
+
+
+
+/*#define MAT_SX 0 /* accessed by REGIND !! */
+#define MAT_SY 20
+#define MAT_SZ 40
+#define MAT_TX 48
+#define MAT_TY 52
+#define MAT_TZ 56
+
+
+
+
+/* Do viewport map, device scale and perspective projection.
+ *
+ * void project_verts( GLfloat *first,
+ * GLfloat *last,
+ * const GLfloat *m,
+ * GLuint stride )
+ *
+ *
+ * Rearrange fxVertices to look like grVertices.
+ */
+
+GLOBL GLNAME( TAG(fx_3dnow_project_vertices) )
+GLNAME( TAG(fx_3dnow_project_vertices) ):
+
+ PUSH_L ( EBP )
+
+ MOV_L ( REGOFF(8, ESP), ECX ) /* first_vert */
+ MOV_L ( REGOFF(12, ESP), EDX ) /* last_vert */
+
+ CMP_L ( ECX, EDX )
+ JE ( TAGLLBL(FXPV_end) )
+
+ FEMMS
+
+ PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */
+
+ MOV_L ( REGOFF(16, ESP), EBP ) /* matrix */
+ MOV_L ( REGOFF(20, ESP), EAX ) /* stride */
+
+ MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */
+ PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */
+
+#if !defined(FX_V2)
+ MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */
+ MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */
+#endif
+
+ MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */
+ PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */
+
+ MOVD ( REGIND(EBP), MM5 )
+ PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */
+
+ MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */
+
+
+ALIGNTEXT32
+TAGLLBL(FXPV_loop_start):
+
+ PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */
+
+
+ MOVD ( REGOFF(12, ECX), MM0 ) /* | f[3] */
+ PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */
+
+ MOVD ( REGOFF(12, ECX), MM7 ) /* | f[3] */
+ PFRCPIT1 ( MM0, MM7 )
+ PFRCPIT2 ( MM0, MM7 ) /* oow | oow */
+
+ PUNPCKLDQ ( MM7, MM7 )
+
+
+#if (TYPE & SETUP_RGBA)
+ MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */
+ MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) )
+#endif
+
+#if (TYPE & SETUP_TMU1)
+ MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */
+ PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */
+ MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) )
+#endif
+
+
+#if (TYPE & SETUP_TMU0)
+ MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */
+ PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */
+ MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) )
+#endif
+
+
+
+
+
+/* DO_SETUP_XYZ */
+
+ MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */
+ PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */
+
+ MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */
+ PFMUL ( MM7, MM3 ) /* | f[2] * oow */
+
+ MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */
+ PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */
+
+ PFADD ( MM0, MM3 ) /* | f[2] += vtz */
+ PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */
+
+ PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */
+
+#if !defined(FX_V2)
+ PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */
+#endif
+
+ MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) )
+ MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) )
+
+
+/* end of DO_SETUP_XYZ */
+
+ MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */
+ ADD_L ( EAX, ECX ) /* f += stride */
+
+ CMP_L ( ECX, EDX ) /* stall??? */
+ JA ( TAGLLBL(FXPV_loop_start) )
+
+TAGLLBL(FXPV_end):
+ FEMMS
+ POP_L ( EBP )
+ RET
+
+
+
+
+
+
+
+/* void project_verts( GLfloat *first,
+ * GLfloat *last,
+ * const GLfloat *m,
+ * GLuint stride,
+ * const GLubyte *mask )
+ *
+ */
+
+GLOBL GLNAME( TAG(fx_3dnow_project_clipped_vertices) )
+GLNAME( TAG(fx_3dnow_project_clipped_vertices) ):
+
+ PUSH_L ( EBP )
+
+ MOV_L ( REGOFF(8, ESP), ECX ) /* first FXDRIVER(VB)->verts*/
+ MOV_L ( REGOFF(12, ESP), EDX ) /* last FXDRIVER(VB)->last_vert */
+
+ FEMMS
+
+ PUSH_L ( EDI )
+ PUSH_L ( ESI )
+
+ PREFETCH ( REGIND(ECX) ) /* fetch the first vertex */
+
+ MOV_L ( REGOFF(24, ESP), EBP ) /* mat ctx->Viewport.WindowMap.M */
+ MOV_L ( REGOFF(28, ESP), EAX ) /* stride */
+ MOV_L ( REGOFF(32, ESP), ESI ) /* VB->ClipMask */
+
+ MOVD ( REGOFF(MAT_TX, EBP), MM6 ) /* | tx */
+ PUNPCKLDQ ( REGOFF(MAT_TY, EBP), MM6 ) /* ty | tx */
+
+#if !defined(FX_V2)
+ MOV_L ( CONST(0x49400000), REGOFF(-8, ESP) ) /* snapper */
+ MOV_L ( CONST(0x49400000), REGOFF(-4, ESP) ) /* snapper */
+#endif
+
+ MOVQ ( REGOFF(-8, ESP), MM4 ) /* snapper | snapper */
+ PFADD ( MM4, MM6 ) /* ty+snapper | tx+snapper */
+
+ MOVD ( REGIND(EBP), MM5 )
+ PUNPCKLDQ ( REGOFF(MAT_SY, EBP), MM5 ) /* vsy | vsx */
+
+ MOVD ( REGOFF(MAT_SZ, EBP), MM1 ) /* | vsz */
+
+
+
+ALIGNTEXT32
+TAGLLBL(FXPCV_loop_start):
+
+ PREFETCH ( REGOFF(64, ECX) ) /* fetch the next-ish vertex */
+
+ CMP_B ( CONST(0), REGIND(ESI) )
+ JNE ( TAGLLBL(FXPCV_skip) )
+
+ MOVD ( REGOFF(12, ECX), MM0) /* | f[3] */
+ PFRCP ( MM0, MM0 ) /* oow = 1/f[3] */
+
+ MOVD ( REGOFF(12, ECX), MM7) /* | f[3] */
+ PFRCPIT1 ( MM0, MM7 )
+ PFRCPIT2 ( MM0, MM7 ) /* oow | oow */
+
+ PUNPCKLDQ ( MM7, MM7 )
+
+
+#if (TYPE & SETUP_RGBA)
+ MOVD ( REGOFF(CLIP_R, ECX ), MM0 ) /* f[RCOORD] = f[CLIP_R]; */
+ MOVD ( MM0, REGOFF(GR_VERTEX_R_OFFSET, ECX) )
+#endif
+
+#if (TYPE & SETUP_TMU1)
+ MOVQ ( REGOFF(CLIP_S1, ECX), MM0 ) /* f[S1COORD] = f[CLIP_S1] * oow */
+ PFMUL ( MM7, MM0 ) /* f[T1COORD] = f[CLIP_T1] * oow */
+ MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU1_OFFSET, ECX) )
+#endif
+
+
+#if (TYPE & SETUP_TMU0)
+ MOVQ ( REGOFF(CLIP_S0, ECX), MM0 ) /* f[S0COORD] = f[CLIP_S0] * oow */
+ PFMUL ( MM7, MM0 ) /* f[T0COORD] = f[CLIP_T0] * oow */
+ MOVQ ( MM0, REGOFF(GR_VERTEX_SOW_TMU0_OFFSET, ECX) )
+#endif
+
+
+
+
+/* DO_SETUP_XYZ */
+
+ MOVQ ( REGIND(ECX), MM2 ) /* f[1] | f[0] */
+ PFMUL ( MM7, MM2 ) /* f[1] * oow | f[0] * oow */
+
+ MOVD ( REGOFF(8, ECX), MM3 ) /* | f[2] */
+ PFMUL ( MM7, MM3 ) /* | f[2] * oow */
+
+ MOVD ( REGOFF(MAT_TZ, EBP), MM0 ) /* | vtz */
+ PFMUL ( MM1, MM3 ) /* | f[2] *= vsz */
+
+ PFADD ( MM0, MM3 ) /* | f[2] += vtz */
+ PFMUL ( MM5, MM2 ) /* f[1] *= vsy | f[0] *= vsx */
+
+ PFADD ( MM6, MM2 ) /* f[1] += vty | f[0] += vtx */
+
+#if !defined(FX_V2)
+ PFSUB ( MM4, MM2 ) /* f[0,1] -= snapper */
+#endif
+
+ MOVQ ( MM2, REGOFF(GR_VERTEX_X_OFFSET, ECX) )
+ MOVD ( MM3, REGOFF(GR_VERTEX_OOZ_OFFSET, ECX) )
+
+
+/* end of DO_SETUP_XYZ */
+
+ MOVD ( MM7, REGOFF(GR_VERTEX_OOW_OFFSET, ECX) ) /* f[OOWCOORD] = oow */
+
+TAGLLBL(FXPCV_skip):
+ ADD_L ( EAX, ECX ) /* f += stride */
+
+ INC_L ( ESI ) /* next ClipMask */
+ CMP_L ( ECX, EDX )
+ JA ( TAGLLBL(FXPCV_loop_start) )
+
+ POP_L ( ESI )
+ POP_L ( EDI )
+
+TAGLLBL(FXPCV_end):
+ FEMMS
+ POP_L ( EBP )
+ RET
+
+
+
+#undef TYPE
+#undef TAG
+#undef SIZE
+
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_render.c b/src/mesa/drivers/dri/tdfx/tdfx_render.c
index 56f5f147eeb..a30ec78a558 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_render.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_render.c
@@ -70,7 +70,7 @@ static void tdfxClear( GLcontext *ctx,
mask &= ~(BUFFER_BIT_ACCUM);
if (mask & BUFFER_BIT_STENCIL) {
- if (!fxMesa->haveHwStencil || ctx->Stencil.WriteMask[0] != 0xff) {
+ if (!fxMesa->haveHwStencil || (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
/* Napalm seems to have trouble with stencil write masks != 0xff */
/* do stencil clear in software */
mask &= ~(BUFFER_BIT_STENCIL);
@@ -98,7 +98,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff);
/* set stencil ref value = desired clear value */
fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS,
- fxMesa->Stencil.Clear, 0xff);
+ (fxMesa->Stencil.Clear & 0xff), 0xff);
fxMesa->Glide.grStencilOp(GR_STENCILOP_REPLACE,
GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE);
fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
@@ -129,7 +129,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
}
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
@@ -152,11 +152,11 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
- fxMesa->Depth.Clear);
+ fxMesa->Depth.Clear & 0xff);
/* clear front */
FX_grColorMaskv_NoLock(ctx, true4);
fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
@@ -164,7 +164,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -181,7 +181,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -198,7 +198,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -215,7 +215,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -225,7 +225,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -242,7 +242,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -254,7 +254,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -272,7 +272,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
else
fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
@@ -293,7 +293,7 @@ static void tdfxClear( GLcontext *ctx,
fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
fxMesa->Color.ClearAlpha,
fxMesa->Depth.Clear,
- (FxU32) ctx->Stencil.Clear);
+ (FxU32) (ctx->Stencil.Clear & 0xff));
if (ctx->Depth.Mask && ctx->Depth.Test) {
fxMesa->Glide.grDepthMask(FXTRUE);
}
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_state.c b/src/mesa/drivers/dri/tdfx/tdfx_state.c
index 1869de47374..a389273b2f0 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_state.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_state.c
@@ -462,9 +462,9 @@ static void tdfxUpdateStencil( GLcontext *ctx )
if (fxMesa->haveHwStencil) {
if (ctx->Stencil.Enabled) {
fxMesa->Stencil.Function = ctx->Stencil.Function[0] - GL_NEVER + GR_CMP_NEVER;
- fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0];
- fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0];
- fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0];
+ fxMesa->Stencil.RefValue = ctx->Stencil.Ref[0] & 0xff;
+ fxMesa->Stencil.ValueMask = ctx->Stencil.ValueMask[0] & 0xff;
+ fxMesa->Stencil.WriteMask = ctx->Stencil.WriteMask[0] & 0xff;
fxMesa->Stencil.FailFunc = convertGLStencilOp(ctx->Stencil.FailFunc[0]);
fxMesa->Stencil.ZFailFunc = convertGLStencilOp(ctx->Stencil.ZFailFunc[0]);
fxMesa->Stencil.ZPassFunc = convertGLStencilOp(ctx->Stencil.ZPassFunc[0]);
diff --git a/src/mesa/drivers/dri/tdfx/tdfx_tex.c b/src/mesa/drivers/dri/tdfx/tdfx_tex.c
index d8a80534bb9..04ddfaad24b 100644
--- a/src/mesa/drivers/dri/tdfx/tdfx_tex.c
+++ b/src/mesa/drivers/dri/tdfx/tdfx_tex.c
@@ -52,7 +52,7 @@
/* no borders! can't halve 1x1! (stride > width * comp) not allowed */
-void
+static void
_mesa_halve2x2_teximage2d ( GLcontext *ctx,
struct gl_texture_image *texImage,
GLuint bytesPerPixel,
@@ -65,6 +65,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx,
GLint srcRowStride = srcWidth * bytesPerPixel;
GLubyte *src = (GLubyte *)srcImage;
GLubyte *dst = dstImage;
+ GLuint dstImageOffsets = 0;
GLuint bpt = 0;
GLubyte *_s = NULL;
@@ -96,7 +97,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx,
&_mesa_texformat_rgba8888_rev, src,
0, 0, 0, /* dstX/Y/Zoffset */
srcRowStride, /* dstRowStride */
- 0, /* dstImageStride */
+ &dstImageOffsets,
srcWidth, srcHeight, 1,
texImage->_BaseFormat, _t, srcImage, &ctx->DefaultPacking);
}
@@ -143,7 +144,7 @@ _mesa_halve2x2_teximage2d ( GLcontext *ctx,
texImage->TexFormat, dstImage,
0, 0, 0, /* dstX/Y/Zoffset */
dstWidth * bpt,
- 0, /* dstImageStride */
+ &dstImageOffsets,
dstWidth, dstHeight, 1,
GL_BGRA, CHAN_TYPE, dst, &ctx->DefaultPacking);
FREE(dst);
@@ -1177,6 +1178,7 @@ adjust2DRatio (GLcontext *ctx,
const GLint newWidth = width * mml->wScale;
const GLint newHeight = height * mml->hScale;
GLvoid *tempImage;
+ GLuint dstImageOffsets = 0;
if (!texImage->IsCompressed) {
GLubyte *destAddr;
@@ -1189,7 +1191,7 @@ adjust2DRatio (GLcontext *ctx,
texImage->TexFormat, tempImage,
0, 0, 0, /* dstX/Y/Zoffset */
width * texelBytes, /* dstRowStride */
- 0, /* dstImageStride */
+ &dstImageOffsets,
width, height, 1,
format, type, pixels, packing);
@@ -1213,6 +1215,7 @@ adjust2DRatio (GLcontext *ctx,
}
tempImage = MALLOC(newWidth * newHeight * rawBytes);
if (!tempImage) {
+ FREE(rawImage);
return GL_FALSE;
}
/* unpack image, apply transfer ops and store in rawImage */
@@ -1220,7 +1223,7 @@ adjust2DRatio (GLcontext *ctx,
&_mesa_texformat_rgba8888_rev, rawImage,
0, 0, 0, /* dstX/Y/Zoffset */
width * rawBytes, /* dstRowStride */
- 0, /* dstImageStride */
+ &dstImageOffsets,
width, height, 1,
format, type, pixels, packing);
_mesa_rescale_teximage2d(rawBytes,
@@ -1233,7 +1236,7 @@ adjust2DRatio (GLcontext *ctx,
texImage->TexFormat, texImage->Data,
xoffset * mml->wScale, yoffset * mml->hScale, 0, /* dstX/Y/Zoffset */
dstRowStride,
- 0, /* dstImageStride */
+ &dstImageOffsets,
newWidth, newHeight, 1,
GL_RGBA, CHAN_TYPE, tempImage, &ctx->DefaultPacking);
FREE(rawImage);
@@ -1257,6 +1260,7 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
GLint texelBytes, dstRowStride;
+ GLuint mesaFormat;
/*
printf("TexImage id=%d int 0x%x format 0x%x type 0x%x %dx%d\n",
@@ -1344,9 +1348,10 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
internalFormat, format, type);
assert(texImage->TexFormat);
- mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
+ mesaFormat = texImage->TexFormat->MesaFormat;
+ mml->glideFormat = fxGlideFormat(mesaFormat);
ti->info.format = mml->glideFormat;
- texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
+ texImage->FetchTexelc = fxFetchFunction(mesaFormat);
texelBytes = texImage->TexFormat->TexelBytes;
if (texImage->IsCompressed) {
@@ -1354,12 +1359,13 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
mml->width,
mml->height,
1,
- internalFormat);
- dstRowStride = _mesa_compressed_row_stride(internalFormat, mml->width);
- texImage->Data = _mesa_malloc(texImage->CompressedSize);
+ mesaFormat);
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width);
+ texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize);
} else {
dstRowStride = mml->width * texelBytes;
- texImage->Data = _mesa_malloc(mml->width * mml->height * texelBytes);
+ texImage->Data = _mesa_alloc_texmemory(mml->width * mml->height *
+ texelBytes);
}
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
@@ -1387,12 +1393,12 @@ tdfxTexImage2D(GLcontext *ctx, GLenum target, GLint level,
/* no rescaling needed */
/* unpack image, apply transfer ops and store in texImage->Data */
texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
- texImage->TexFormat, texImage->Data,
- 0, 0, 0, /* dstX/Y/Zoffset */
- dstRowStride,
- 0, /* dstImageStride */
- width, height, 1,
- format, type, pixels, packing);
+ texImage->TexFormat, texImage->Data,
+ 0, 0, 0, /* dstX/Y/Zoffset */
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, pixels, packing);
}
/* GL_SGIS_generate_mipmap */
@@ -1473,7 +1479,7 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
texelBytes = texImage->TexFormat->TexelBytes;
if (texImage->IsCompressed) {
- dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, mml->width);
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, mml->width);
} else {
dstRowStride = mml->width * texelBytes;
}
@@ -1497,12 +1503,12 @@ tdfxTexSubImage2D(GLcontext *ctx, GLenum target, GLint level,
else {
/* no rescaling needed */
texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
- texImage->TexFormat, texImage->Data,
- xoffset, yoffset, 0,
- dstRowStride,
- 0, /* dstImageStride */
- width, height, 1,
- format, type, pixels, packing);
+ texImage->TexFormat, texImage->Data,
+ xoffset, yoffset, 0,
+ dstRowStride,
+ texImage->ImageOffsets,
+ width, height, 1,
+ format, type, pixels, packing);
}
/* GL_SGIS_generate_mipmap */
@@ -1600,6 +1606,7 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target,
tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
tdfxTexInfo *ti;
tdfxMipMapLevel *mml;
+ GLuint mesaFormat;
if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
fprintf(stderr, "tdfxCompressedTexImage2D: id=%d int 0x%x %dx%d\n",
@@ -1651,9 +1658,10 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target,
/* Determine the appropriate Glide texel format,
* given the user's internal texture format hint.
*/
- mml->glideFormat = fxGlideFormat(texImage->TexFormat->MesaFormat);
+ mesaFormat = texImage->TexFormat->MesaFormat;
+ mml->glideFormat = fxGlideFormat(mesaFormat);
ti->info.format = mml->glideFormat;
- texImage->FetchTexelc = fxFetchFunction(texImage->TexFormat->MesaFormat);
+ texImage->FetchTexelc = fxFetchFunction(mesaFormat);
/* allocate new storage for texture image, if needed */
if (!texImage->Data) {
@@ -1661,8 +1669,8 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target,
mml->width,
mml->height,
1,
- internalFormat);
- texImage->Data = _mesa_malloc(texImage->CompressedSize);
+ mesaFormat);
+ texImage->Data = _mesa_alloc_texmemory(texImage->CompressedSize);
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
return;
@@ -1685,9 +1693,10 @@ tdfxCompressedTexImage2D (GLcontext *ctx, GLenum target,
* we replicate the data over the padded area.
* For now, we take 2) + 3) but texelfetchers will be wrong!
*/
- GLuint srcRowStride = _mesa_compressed_row_stride(internalFormat, width);
+ const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
+ GLuint srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
- GLuint destRowStride = _mesa_compressed_row_stride(internalFormat,
+ GLuint destRowStride = _mesa_compressed_row_stride(mesaFormat,
mml->width);
_mesa_upscale_teximage2d(srcRowStride, (height+3) / 4,
@@ -1726,6 +1735,7 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
GLint destRowStride, srcRowStride;
GLint i, rows;
GLubyte *dest;
+ const GLuint mesaFormat = texImage->TexFormat->MesaFormat;
if (TDFX_DEBUG & DEBUG_VERBOSE_DRI) {
fprintf(stderr, "tdfxCompressedTexSubImage2D: id=%d\n", texObj->Name);
@@ -1736,12 +1746,11 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
mml = TDFX_TEXIMAGE_DATA(texImage);
assert(mml);
- srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, width);
+ srcRowStride = _mesa_compressed_row_stride(mesaFormat, width);
- destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
- mml->width);
+ destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width);
dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
- texImage->InternalFormat,
+ mesaFormat,
mml->width,
(GLubyte*) texImage->Data);
@@ -1757,10 +1766,9 @@ tdfxCompressedTexSubImage2D( GLcontext *ctx, GLenum target,
* see fxDDCompressedTexImage2D for caveats
*/
if (mml->wScale != 1 || mml->hScale != 1) {
- srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, texImage->Width);
+ srcRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width);
- destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
- mml->width);
+ destRowStride = _mesa_compressed_row_stride(mesaFormat, mml->width);
_mesa_upscale_teximage2d(srcRowStride, texImage->Height / 4,
destRowStride, mml->height / 4,
1, texImage->Data, destRowStride,
diff --git a/src/mesa/drivers/dri/unichrome/via_ioctl.c b/src/mesa/drivers/dri/unichrome/via_ioctl.c
index 1daf49f151f..c8c6dc01933 100644
--- a/src/mesa/drivers/dri/unichrome/via_ioctl.c
+++ b/src/mesa/drivers/dri/unichrome/via_ioctl.c
@@ -233,7 +233,7 @@ static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
if (mask & BUFFER_BIT_STENCIL) {
if (vmesa->have_hw_stencil) {
- if (ctx->Stencil.WriteMask[0] == 0xff) {
+ if ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff) {
flag |= VIA_DEPTH;
clear_depth &= ~0xff;
clear_depth |= (ctx->Stencil.Clear & 0xff);
diff --git a/src/mesa/drivers/dri/unichrome/via_tex.c b/src/mesa/drivers/dri/unichrome/via_tex.c
index 19b270955eb..b344c009318 100644
--- a/src/mesa/drivers/dri/unichrome/via_tex.c
+++ b/src/mesa/drivers/dri/unichrome/via_tex.c
@@ -691,6 +691,14 @@ static void viaTexImage(GLcontext *ctx,
}
texelBytes = texImage->TexFormat->TexelBytes;
+ if (texelBytes == 0) {
+ /* compressed format */
+ texImage->IsCompressed = GL_TRUE;
+ texImage->CompressedSize =
+ ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
+ texImage->Height, texImage->Depth,
+ texImage->TexFormat->MesaFormat);
+ }
/* Minimum pitch of 32 bytes */
if (postConvWidth * texelBytes < 32) {
@@ -779,10 +787,10 @@ static void viaTexImage(GLcontext *ctx,
return;
}
else {
- GLint dstRowStride, dstImageStride = 0;
+ GLint dstRowStride;
GLboolean success;
if (texImage->IsCompressed) {
- dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width);
+ dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
}
else {
dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
@@ -793,7 +801,8 @@ static void viaTexImage(GLcontext *ctx,
texImage->TexFormat,
texImage->Data,
0, 0, 0, /* dstX/Y/Zoffset */
- dstRowStride, dstImageStride,
+ dstRowStride,
+ texImage->ImageOffsets,
width, height, 1,
format, type, pixels, packing);
if (!success) {
diff --git a/src/mesa/drivers/dri/unichrome/via_tris.c b/src/mesa/drivers/dri/unichrome/via_tris.c
index 9cb88ae2399..4cc7942b1b6 100644
--- a/src/mesa/drivers/dri/unichrome/via_tris.c
+++ b/src/mesa/drivers/dri/unichrome/via_tris.c
@@ -744,16 +744,18 @@ static void viaChooseVertexState( GLcontext *ctx )
{
struct via_context *vmesa = VIA_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z;
GLuint setupIndex = 0;
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
vmesa->vertex_attr_count = 0;
/* EMIT_ATTR's must be in order as they tell t_vertex.c how to
* build up a hardware vertex.
*/
- if (index & (_TNL_BITS_TEX_ANY|_TNL_BIT_FOG)) {
+ if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W );
vmesa->coloroffset = 4;
}
@@ -767,8 +769,9 @@ static void viaChooseVertexState( GLcontext *ctx )
HC_HVPMSK_Cd );
vmesa->specoffset = 0;
- if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
- if ((index & _TNL_BIT_COLOR1)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
+ RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
vmesa->specoffset = vmesa->coloroffset + 1;
EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC,
HC_HVPMSK_Cs );
@@ -776,13 +779,13 @@ static void viaChooseVertexState( GLcontext *ctx )
else
EMIT_PAD( 3 );
- if ((index & _TNL_BIT_FOG))
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs );
else
EMIT_PAD( 1 );
}
- if (index & _TNL_BIT_TEX(0)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
if (vmesa->ptexHack)
EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0,
(HC_HVPMSK_S | HC_HVPMSK_T) );
@@ -791,7 +794,7 @@ static void viaChooseVertexState( GLcontext *ctx )
(HC_HVPMSK_S | HC_HVPMSK_T) );
}
- if (index & _TNL_BIT_TEX(1)) {
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1,
(HC_HVPMSK_S | HC_HVPMSK_T) );
}
@@ -824,17 +827,19 @@ static GLboolean viaCheckPTexHack( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
- GLuint index = tnl->render_inputs;
+ DECLARE_RENDERINPUTS(index_bitset);
GLboolean fallback = GL_FALSE;
GLboolean ptexHack = GL_FALSE;
- if (index & _TNL_BIT_TEX(0) && VB->TexCoordPtr[0]->size == 4) {
- if ((index & _TNL_BITS_TEX_ANY) == _TNL_BIT_TEX(0))
+ RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
+
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) {
+ if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
ptexHack = GL_TRUE;
else
fallback = GL_TRUE;
}
- if ((index & _TNL_BIT_TEX(1)) && VB->TexCoordPtr[1]->size == 4)
+ if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4)
fallback = GL_TRUE;
FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback);
diff --git a/src/mesa/drivers/ggi/default/.cvsignore b/src/mesa/drivers/ggi/default/.cvsignore
new file mode 100644
index 00000000000..c8a526b14d7
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/.cvsignore
@@ -0,0 +1 @@
+genkgi.conf
diff --git a/src/mesa/drivers/ggi/default/genkgi.h b/src/mesa/drivers/ggi/default/genkgi.h
new file mode 100644
index 00000000000..1202150060b
--- /dev/null
+++ b/src/mesa/drivers/ggi/default/genkgi.h
@@ -0,0 +1,76 @@
+/* $Id: genkgi.h,v 1.3 1999-08-22 08:56:50 jtaylor Exp $
+******************************************************************************
+
+ GGIMesa - KGIcon specific overrides for fbcon-mesa
+ API header
+
+ Copyright (C) 1999 Jon Taylor [[email protected]]
+
+ 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
+ THE AUTHOR(S) 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 _GENKGI_MESA_H
+#define _GENKGI_MESA_H
+
+#undef KGI_USE_PPBUFS
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <ggi/internal/ggi-dl.h>
+#include <ggi/mesa/display_fbdev.h>
+#include <kgi/kgi.h>
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+/* FIXME: LibGGI needs to export its genkgi.h */
+struct genkgi_priv
+{
+ ggi_gc *mapped_gc;
+ unsigned int gc_size;
+ ggifunc_drawline *drawline;
+ ggifunc_drawbox *drawbox;
+ ggifunc_fillscreen *fillscreen;
+ int fd_gc;
+ int close_gc;
+ int fd_kgicommand;
+ uint8 *mapped_kgicommand;
+ uint8 *kgicommand_ptr;
+ unsigned int kgicommand_buffersize;
+};
+
+#define GENKGI_PRIV(vis) ((struct genkgi_priv *)FBDEV_PRIV(vis)->accelpriv)
+
+extern ggifunc_getapi GGIMesa_genkgi_getapi;
+extern ggifunc_flush GGIMesa_genkgi_flush;
+
+struct genkgi_priv_mesa
+{
+ char accel[100];
+ int have_accel;
+ void *accelpriv; /* Private data of subdrivers */
+ struct genkgi_priv *oldpriv; /* LibGGI's private data */
+};
+
+#define GENKGI_PRIV_MESA(vis) ((struct genkgi_priv_mesa *)FBDEV_PRIV_MESA(vis)->accelpriv)
+
+#endif /* _GENKHI_MESA_H */
diff --git a/src/mesa/drivers/ggi/default/genkgi_mode.c b/src/mesa/drivers/ggi/default/genkgi_mode.c
index 938024789f9..a81f553f49b 100644
--- a/src/mesa/drivers/ggi/default/genkgi_mode.c
+++ b/src/mesa/drivers/ggi/default/genkgi_mode.c
@@ -1,4 +1,4 @@
-/* $Id: genkgi_mode.c,v 1.4 2000/01/07 08:34:44 jtaylor Exp $
+/* $Id: genkgi_mode.c,v 1.4 2000-01-07 08:34:44 jtaylor Exp $
******************************************************************************
display-fbdev-kgicon-generic-mesa
diff --git a/src/mesa/drivers/ggi/default/genkgi_visual.c b/src/mesa/drivers/ggi/default/genkgi_visual.c
index 17ef9679bb8..1b49a4ae528 100644
--- a/src/mesa/drivers/ggi/default/genkgi_visual.c
+++ b/src/mesa/drivers/ggi/default/genkgi_visual.c
@@ -1,4 +1,4 @@
-/* $Id: genkgi_visual.c,v 1.7 2000/06/11 20:11:55 jtaylor Exp $
+/* $Id: genkgi_visual.c,v 1.7 2000-06-11 20:11:55 jtaylor Exp $
******************************************************************************
genkgi_visual.c: visual handling for the generic KGI helper
diff --git a/src/mesa/drivers/ggi/display/.cvsignore b/src/mesa/drivers/ggi/display/.cvsignore
new file mode 100644
index 00000000000..98858db2c0e
--- /dev/null
+++ b/src/mesa/drivers/ggi/display/.cvsignore
@@ -0,0 +1 @@
+fbdev.conf
diff --git a/src/mesa/drivers/ggi/include/ggi/mesa/debug.h b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h
index 35d11624c64..e4c2a250454 100644
--- a/src/mesa/drivers/ggi/include/ggi/mesa/debug.h
+++ b/src/mesa/drivers/ggi/include/ggi/mesa/debug.h
@@ -1,4 +1,4 @@
-/* $Id: debug.h,v 1.5 2003/09/22 15:18:51 brianp Exp $
+/* $Id: debug.h,v 1.5 2003-09-22 15:18:51 brianp Exp $
******************************************************************************
GGIMesa debugging macros
diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c
index 2ba3b81706c..942692c8bb0 100644
--- a/src/mesa/drivers/osmesa/osmesa.c
+++ b/src/mesa/drivers/osmesa/osmesa.c
@@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 6.5.1
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
@@ -38,7 +38,6 @@
#include "context.h"
#include "extensions.h"
#include "framebuffer.h"
-#include "fbobject.h"
#include "imports.h"
#include "mtypes.h"
#include "renderbuffer.h"
@@ -46,7 +45,6 @@
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "swrast/s_context.h"
-#include "swrast/s_depth.h"
#include "swrast/s_lines.h"
#include "swrast/s_triangle.h"
#include "tnl/tnl.h"
@@ -56,32 +54,32 @@
-/*
- * This is the OS/Mesa context struct.
- * Notice how it includes a GLcontext. By doing this we're mimicking
- * C++ inheritance/derivation.
- * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
- * or vice versa.
+/**
+ * OSMesa rendering context, derived from core Mesa GLcontext.
*/
-struct osmesa_context {
- GLcontext mesa; /* 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 */
- GLint rowlength; /* number of pixels per row */
- GLint userRowLength; /* user-specified number of pixels per row */
- GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
- GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */
- GLboolean yup; /* TRUE -> Y increases upward */
- /* FALSE -> Y increases downward */
+struct osmesa_context
+{
+ GLcontext mesa; /*< Base class - this must be first */
+ GLvisual *gl_visual; /*< Describes the buffers */
+ struct gl_renderbuffer *rb; /*< The user's colorbuffer */
+ GLframebuffer *gl_buffer; /*< The framebuffer, containing user's rb */
+ GLenum format; /*< User-specified context format */
+ GLint width, height; /*< size of image buffer */
+ GLint rowlength; /*< number of pixels per row */
+ GLint userRowLength; /*< user-specified number of pixels per row */
+ GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
+ GLvoid *rowaddr[MAX_HEIGHT]; /*< address of first pixel in each image row */
+ GLboolean yup; /*< TRUE -> Y increases upward */
+ /*< FALSE -> Y increases downward */
};
-/* Just cast, since we're using structure containment */
-#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx))
-
+static INLINE OSMesaContext
+OSMESA_CONTEXT(GLcontext *ctx)
+{
+ /* Just cast, since we're using structure containment */
+ return (OSMesaContext) ctx;
+}
/**********************************************************************/
@@ -119,7 +117,7 @@ osmesa_update_state( GLcontext *ctx, GLuint new_state )
}
-/*
+/**
* Just return the current buffer size.
* There's no window to track the size of.
*/
@@ -141,26 +139,39 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
/***** Read/write spans/arrays of pixels *****/
/**********************************************************************/
-/* RGBA */
-#define NAME(PREFIX) PREFIX##_RGBA
-#define FORMAT GL_RGBA
+/* 8-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA8
+#define RB_TYPE GLubyte
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
- GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+ GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
#define INC_PIXEL_PTR(P) P += 4
-#if CHAN_TYPE == GL_FLOAT
#define STORE_PIXEL(DST, X, Y, VALUE) \
- DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
- DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
- DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
- DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, CHAN_MAXF)
+ DST[0] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[BCOMP]; \
+ DST[3] = VALUE[ACOMP]
#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
- DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
- DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
- DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
- DST[3] = CHAN_MAXF
-#else
+ DST[0] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[BCOMP]; \
+ DST[3] = 255
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[0]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[2]; \
+ DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
+
+/* 16-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
#define STORE_PIXEL(DST, X, Y, VALUE) \
DST[0] = VALUE[RCOMP]; \
DST[1] = VALUE[GCOMP]; \
@@ -170,8 +181,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[0] = VALUE[RCOMP]; \
DST[1] = VALUE[GCOMP]; \
DST[2] = VALUE[BCOMP]; \
- DST[3] = CHAN_MAX
-#endif
+ DST[3] = 65535
#define FETCH_PIXEL(DST, SRC) \
DST[RCOMP] = SRC[0]; \
DST[GCOMP] = SRC[1]; \
@@ -179,13 +189,89 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[ACOMP] = SRC[3]
#include "swrast/s_spantemp.h"
-/* BGRA */
-#define NAME(PREFIX) PREFIX##_BGRA
-#define FORMAT GL_RGBA
+/* 32-bit RGBA */
+#define NAME(PREFIX) PREFIX##_RGBA32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
+ DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
+ DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
+ DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F)
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
+ DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
+ DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
+ DST[3] = 1.0F
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[0]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[2]; \
+ DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]; \
+ DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]; \
+ DST[3] = 255
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
+
+/* 16-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]; \
+ DST[3] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]; \
+ DST[3] = 65535
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = SRC[3]
+#include "swrast/s_spantemp.h"
+
+/* 32-bit BGRA */
+#define NAME(PREFIX) PREFIX##_BGRA32
+#define RB_TYPE GLfloat
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
- GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+ GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
#define INC_PIXEL_PTR(P) P += 4
#define STORE_PIXEL(DST, X, Y, VALUE) \
DST[2] = VALUE[RCOMP]; \
@@ -196,7 +282,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[2] = VALUE[RCOMP]; \
DST[1] = VALUE[GCOMP]; \
DST[0] = VALUE[BCOMP]; \
- DST[3] = CHAN_MAX
+ DST[3] = 1.0F
#define FETCH_PIXEL(DST, SRC) \
DST[RCOMP] = SRC[2]; \
DST[GCOMP] = SRC[1]; \
@@ -204,13 +290,14 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[ACOMP] = SRC[3]
#include "swrast/s_spantemp.h"
-/* ARGB */
-#define NAME(PREFIX) PREFIX##_ARGB
-#define FORMAT GL_RGBA
+
+/* 8-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB8
+#define RB_TYPE GLubyte
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
- GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
+ GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
#define INC_PIXEL_PTR(P) P += 4
#define STORE_PIXEL(DST, X, Y, VALUE) \
DST[1] = VALUE[RCOMP]; \
@@ -221,7 +308,7 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[1] = VALUE[RCOMP]; \
DST[2] = VALUE[GCOMP]; \
DST[3] = VALUE[BCOMP]; \
- DST[0] = CHAN_MAX
+ DST[0] = 255
#define FETCH_PIXEL(DST, SRC) \
DST[RCOMP] = SRC[1]; \
DST[GCOMP] = SRC[2]; \
@@ -229,13 +316,64 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[ACOMP] = SRC[0]
#include "swrast/s_spantemp.h"
-/* RGB */
-#define NAME(PREFIX) PREFIX##_RGB
-#define FORMAT GL_RGBA
+/* 16-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB16
+#define RB_TYPE GLushort
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
- GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[1] = VALUE[RCOMP]; \
+ DST[2] = VALUE[GCOMP]; \
+ DST[3] = VALUE[BCOMP]; \
+ DST[0] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[1] = VALUE[RCOMP]; \
+ DST[2] = VALUE[GCOMP]; \
+ DST[3] = VALUE[BCOMP]; \
+ DST[0] = 65535
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[1]; \
+ DST[GCOMP] = SRC[2]; \
+ DST[BCOMP] = SRC[3]; \
+ DST[ACOMP] = SRC[0]
+#include "swrast/s_spantemp.h"
+
+/* 32-bit ARGB */
+#define NAME(PREFIX) PREFIX##_ARGB32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[1] = VALUE[RCOMP]; \
+ DST[2] = VALUE[GCOMP]; \
+ DST[3] = VALUE[BCOMP]; \
+ DST[0] = VALUE[ACOMP]
+#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
+ DST[1] = VALUE[RCOMP]; \
+ DST[2] = VALUE[GCOMP]; \
+ DST[3] = VALUE[BCOMP]; \
+ DST[0] = 1.0F
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[1]; \
+ DST[GCOMP] = SRC[2]; \
+ DST[BCOMP] = SRC[3]; \
+ DST[ACOMP] = SRC[0]
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB8
+#define RB_TYPE GLubyte
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
#define INC_PIXEL_PTR(P) P += 3
#define STORE_PIXEL(DST, X, Y, VALUE) \
DST[0] = VALUE[RCOMP]; \
@@ -245,16 +383,55 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[RCOMP] = SRC[0]; \
DST[GCOMP] = SRC[1]; \
DST[BCOMP] = SRC[2]; \
- DST[ACOMP] = CHAN_MAX
+ DST[ACOMP] = 255
+#include "swrast/s_spantemp.h"
+
+/* 16-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[0]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[2]; \
+ DST[ACOMP] = 65535U
+#include "swrast/s_spantemp.h"
+
+/* 32-bit RGB */
+#define NAME(PREFIX) PREFIX##_RGB32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[0] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[2] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[0]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[2]; \
+ DST[ACOMP] = 1.0F
#include "swrast/s_spantemp.h"
-/* BGR */
-#define NAME(PREFIX) PREFIX##_BGR
-#define FORMAT GL_RGBA
+
+/* 8-bit BGR */
+#define NAME(PREFIX) PREFIX##_BGR8
+#define RB_TYPE GLubyte
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
- GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
+ GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
#define INC_PIXEL_PTR(P) P += 3
#define STORE_PIXEL(DST, X, Y, VALUE) \
DST[2] = VALUE[RCOMP]; \
@@ -264,13 +441,51 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[RCOMP] = SRC[2]; \
DST[GCOMP] = SRC[1]; \
DST[BCOMP] = SRC[0]; \
- DST[ACOMP] = CHAN_MAX
+ DST[ACOMP] = 255
#include "swrast/s_spantemp.h"
-/* 16-bit RGB */
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
+/* 16-bit BGR */
+#define NAME(PREFIX) PREFIX##_BGR16
+#define RB_TYPE GLushort
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = 65535
+#include "swrast/s_spantemp.h"
+
+/* 32-bit BGR */
+#define NAME(PREFIX) PREFIX##_BGR32
+#define RB_TYPE GLfloat
+#define SPAN_VARS \
+ const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+#define INIT_PIXEL_PTR(P, X, Y) \
+ GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_PIXEL(DST, X, Y, VALUE) \
+ DST[2] = VALUE[RCOMP]; \
+ DST[1] = VALUE[GCOMP]; \
+ DST[0] = VALUE[BCOMP]
+#define FETCH_PIXEL(DST, SRC) \
+ DST[RCOMP] = SRC[2]; \
+ DST[GCOMP] = SRC[1]; \
+ DST[BCOMP] = SRC[0]; \
+ DST[ACOMP] = 1.0F
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit 5/6/5 RGB */
#define NAME(PREFIX) PREFIX##_RGB_565
-#define FORMAT GL_RGBA
+#define RB_TYPE GLubyte
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
@@ -284,11 +499,12 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC) ) & 0x7) ); \
DST[ACOMP] = CHAN_MAX
#include "swrast/s_spantemp.h"
-#endif /* CHAN_TYPE == GL_UNSIGNED_BYTE */
+
/* color index */
#define NAME(PREFIX) PREFIX##_CI
-#define FORMAT GL_COLOR_INDEX8_EXT
+#define CI_MODE
+#define RB_TYPE GLubyte
#define SPAN_VARS \
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
#define INIT_PIXEL_PTR(P, X, Y) \
@@ -303,20 +519,11 @@ get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
-/**********************************************************************/
-/***** Optimized line rendering *****/
-/**********************************************************************/
-
+/**
+ * Macros for optimized line/triangle rendering.
+ * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
+ */
-#if CHAN_TYPE == GL_FLOAT
-#define PACK_RGBA(DST, R, G, B, A) \
-do { \
- (DST)[0] = MAX2( R, 0.0F ); \
- (DST)[1] = MAX2( G, 0.0F ); \
- (DST)[2] = MAX2( B, 0.0F ); \
- (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
-} while (0)
-#else
#define PACK_RGBA(DST, R, G, B, A) \
do { \
(DST)[osmesa->rInd] = R; \
@@ -324,39 +531,11 @@ do { \
(DST)[osmesa->bInd] = B; \
(DST)[osmesa->aInd] = A; \
} while (0)
-#endif
-
-#define PACK_RGB(DST, R, G, B) \
-do { \
- (DST)[0] = R; \
- (DST)[1] = G; \
- (DST)[2] = B; \
-} while (0)
-#define PACK_BGR(DST, R, G, B) \
-do { \
- (DST)[0] = B; \
- (DST)[1] = G; \
- (DST)[2] = R; \
-} while (0)
-
-#define PACK_RGB_565(DST, R, G, B) \
-do { \
- (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
-} while (0)
+#define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
-#define UNPACK_RED(P) ( (P)[osmesa->rInd] )
-#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] )
-#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] )
-#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] )
-#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X))
-#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X))
-#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X))
-#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X))
-
-
-/*
+/**
* Draw a flat-shaded, RGB line into an osmesa buffer.
*/
#define NAME flat_rgba_line
@@ -379,7 +558,7 @@ do { \
-/*
+/**
* Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
*/
#define NAME flat_rgba_z_line
@@ -408,9 +587,9 @@ do { \
-/*
+/**
* Analyze context state to see if we can provide a fast line drawing
- * function, like those in lines.c. Otherwise, return NULL.
+ * function. Otherwise, return NULL.
*/
static swrast_line_func
osmesa_choose_line_function( GLcontext *ctx )
@@ -518,8 +697,8 @@ osmesa_choose_line_function( GLcontext *ctx )
-/*
- * Return pointer to an accelerated triangle function if possible.
+/**
+ * Return pointer to an optimized triangle function if possible.
*/
static swrast_tri_func
osmesa_choose_triangle_function( GLcontext *ctx )
@@ -600,73 +779,170 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
+ GLint bpc; /* bits per channel */
+
+ if (rb->DataType == GL_UNSIGNED_BYTE)
+ bpc = 8;
+ else if (rb->DataType == GL_UNSIGNED_SHORT)
+ bpc = 16;
+ else
+ bpc = 32;
/* Note: we can ignoring internalFormat for "window-system" renderbuffers */
+ (void) internalFormat;
+
if (osmesa->format == OSMESA_RGBA) {
- rb->GetRow = get_row_RGBA;
- rb->GetValues = get_values_RGBA;
- rb->PutRow = put_row_RGBA;
- rb->PutRowRGB = put_row_rgb_RGBA;
- rb->PutMonoRow = put_mono_row_RGBA;
- rb->PutValues = put_values_RGBA;
- rb->PutMonoValues = put_mono_values_RGBA;
- rb->RedBits =
- rb->GreenBits =
- rb->BlueBits =
- rb->AlphaBits = 8 * sizeof(GLchan);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ rb->GetRow = get_row_RGBA8;
+ rb->GetValues = get_values_RGBA8;
+ rb->PutRow = put_row_RGBA8;
+ rb->PutRowRGB = put_row_rgb_RGBA8;
+ rb->PutMonoRow = put_mono_row_RGBA8;
+ rb->PutValues = put_values_RGBA8;
+ rb->PutMonoValues = put_mono_values_RGBA8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ rb->GetRow = get_row_RGBA16;
+ rb->GetValues = get_values_RGBA16;
+ rb->PutRow = put_row_RGBA16;
+ rb->PutRowRGB = put_row_rgb_RGBA16;
+ rb->PutMonoRow = put_mono_row_RGBA16;
+ rb->PutValues = put_values_RGBA16;
+ rb->PutMonoValues = put_mono_values_RGBA16;
+ }
+ else {
+ rb->GetRow = get_row_RGBA32;
+ rb->GetValues = get_values_RGBA32;
+ rb->PutRow = put_row_RGBA32;
+ rb->PutRowRGB = put_row_rgb_RGBA32;
+ rb->PutMonoRow = put_mono_row_RGBA32;
+ rb->PutValues = put_values_RGBA32;
+ rb->PutMonoValues = put_mono_values_RGBA32;
+ }
+ rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
}
else if (osmesa->format == OSMESA_BGRA) {
- rb->GetRow = get_row_BGRA;
- rb->GetValues = get_values_BGRA;
- rb->PutRow = put_row_BGRA;
- rb->PutRowRGB = put_row_rgb_BGRA;
- rb->PutMonoRow = put_mono_row_BGRA;
- rb->PutValues = put_values_BGRA;
- rb->PutMonoValues = put_mono_values_BGRA;
- rb->RedBits =
- rb->GreenBits =
- rb->BlueBits =
- rb->AlphaBits = 8 * sizeof(GLchan);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ rb->GetRow = get_row_BGRA8;
+ rb->GetValues = get_values_BGRA8;
+ rb->PutRow = put_row_BGRA8;
+ rb->PutRowRGB = put_row_rgb_BGRA8;
+ rb->PutMonoRow = put_mono_row_BGRA8;
+ rb->PutValues = put_values_BGRA8;
+ rb->PutMonoValues = put_mono_values_BGRA8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ rb->GetRow = get_row_BGRA16;
+ rb->GetValues = get_values_BGRA16;
+ rb->PutRow = put_row_BGRA16;
+ rb->PutRowRGB = put_row_rgb_BGRA16;
+ rb->PutMonoRow = put_mono_row_BGRA16;
+ rb->PutValues = put_values_BGRA16;
+ rb->PutMonoValues = put_mono_values_BGRA16;
+ }
+ else {
+ rb->GetRow = get_row_BGRA32;
+ rb->GetValues = get_values_BGRA32;
+ rb->PutRow = put_row_BGRA32;
+ rb->PutRowRGB = put_row_rgb_BGRA32;
+ rb->PutMonoRow = put_mono_row_BGRA32;
+ rb->PutValues = put_values_BGRA32;
+ rb->PutMonoValues = put_mono_values_BGRA32;
+ }
+ rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
}
else if (osmesa->format == OSMESA_ARGB) {
- rb->GetRow = get_row_ARGB;
- rb->GetValues = get_values_ARGB;
- rb->PutRow = put_row_ARGB;
- rb->PutRowRGB = put_row_rgb_ARGB;
- rb->PutMonoRow = put_mono_row_ARGB;
- rb->PutValues = put_values_ARGB;
- rb->PutMonoValues = put_mono_values_ARGB;
- rb->RedBits =
- rb->GreenBits =
- rb->BlueBits =
- rb->AlphaBits = 8 * sizeof(GLchan);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ rb->GetRow = get_row_ARGB8;
+ rb->GetValues = get_values_ARGB8;
+ rb->PutRow = put_row_ARGB8;
+ rb->PutRowRGB = put_row_rgb_ARGB8;
+ rb->PutMonoRow = put_mono_row_ARGB8;
+ rb->PutValues = put_values_ARGB8;
+ rb->PutMonoValues = put_mono_values_ARGB8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ rb->GetRow = get_row_ARGB16;
+ rb->GetValues = get_values_ARGB16;
+ rb->PutRow = put_row_ARGB16;
+ rb->PutRowRGB = put_row_rgb_ARGB16;
+ rb->PutMonoRow = put_mono_row_ARGB16;
+ rb->PutValues = put_values_ARGB16;
+ rb->PutMonoValues = put_mono_values_ARGB16;
+ }
+ else {
+ rb->GetRow = get_row_ARGB32;
+ rb->GetValues = get_values_ARGB32;
+ rb->PutRow = put_row_ARGB32;
+ rb->PutRowRGB = put_row_rgb_ARGB32;
+ rb->PutMonoRow = put_mono_row_ARGB32;
+ rb->PutValues = put_values_ARGB32;
+ rb->PutMonoValues = put_mono_values_ARGB32;
+ }
+ rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
}
else if (osmesa->format == OSMESA_RGB) {
- rb->GetRow = get_row_RGB;
- rb->GetValues = get_values_RGB;
- rb->PutRow = put_row_RGB;
- rb->PutRowRGB = put_row_rgb_RGB;
- rb->PutMonoRow = put_mono_row_RGB;
- rb->PutValues = put_values_RGB;
- rb->PutMonoValues = put_mono_values_RGB;
- rb->RedBits =
- rb->GreenBits =
- rb->BlueBits = 8 * sizeof(GLchan);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ rb->GetRow = get_row_RGB8;
+ rb->GetValues = get_values_RGB8;
+ rb->PutRow = put_row_RGB8;
+ rb->PutRowRGB = put_row_rgb_RGB8;
+ rb->PutMonoRow = put_mono_row_RGB8;
+ rb->PutValues = put_values_RGB8;
+ rb->PutMonoValues = put_mono_values_RGB8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ rb->GetRow = get_row_RGB16;
+ rb->GetValues = get_values_RGB16;
+ rb->PutRow = put_row_RGB16;
+ rb->PutRowRGB = put_row_rgb_RGB16;
+ rb->PutMonoRow = put_mono_row_RGB16;
+ rb->PutValues = put_values_RGB16;
+ rb->PutMonoValues = put_mono_values_RGB16;
+ }
+ else {
+ rb->GetRow = get_row_RGB32;
+ rb->GetValues = get_values_RGB32;
+ rb->PutRow = put_row_RGB32;
+ rb->PutRowRGB = put_row_rgb_RGB32;
+ rb->PutMonoRow = put_mono_row_RGB32;
+ rb->PutValues = put_values_RGB32;
+ rb->PutMonoValues = put_mono_values_RGB32;
+ }
+ rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
}
else if (osmesa->format == OSMESA_BGR) {
- rb->GetRow = get_row_BGR;
- rb->GetValues = get_values_BGR;
- rb->PutRow = put_row_BGR;
- rb->PutRowRGB = put_row_rgb_BGR;
- rb->PutMonoRow = put_mono_row_BGR;
- rb->PutValues = put_values_BGR;
- rb->PutMonoValues = put_mono_values_BGR;
- rb->RedBits =
- rb->GreenBits =
- rb->BlueBits = 8 * sizeof(GLchan);
+ if (rb->DataType == GL_UNSIGNED_BYTE) {
+ rb->GetRow = get_row_BGR8;
+ rb->GetValues = get_values_BGR8;
+ rb->PutRow = put_row_BGR8;
+ rb->PutRowRGB = put_row_rgb_BGR8;
+ rb->PutMonoRow = put_mono_row_BGR8;
+ rb->PutValues = put_values_BGR8;
+ rb->PutMonoValues = put_mono_values_BGR8;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ rb->GetRow = get_row_BGR16;
+ rb->GetValues = get_values_BGR16;
+ rb->PutRow = put_row_BGR16;
+ rb->PutRowRGB = put_row_rgb_BGR16;
+ rb->PutMonoRow = put_mono_row_BGR16;
+ rb->PutValues = put_values_BGR16;
+ rb->PutMonoValues = put_mono_values_BGR16;
+ }
+ else {
+ rb->GetRow = get_row_BGR32;
+ rb->GetValues = get_values_BGR32;
+ rb->PutRow = put_row_BGR32;
+ rb->PutRowRGB = put_row_rgb_BGR32;
+ rb->PutMonoRow = put_mono_row_BGR32;
+ rb->PutValues = put_values_BGR32;
+ rb->PutMonoValues = put_mono_values_BGR32;
+ }
+ rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
}
-#if CHAN_TYPE == GL_UNSIGNED_BYTE
else if (osmesa->format == OSMESA_RGB_565) {
+ ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
rb->GetRow = get_row_RGB_565;
rb->GetValues = get_values_RGB_565;
rb->PutRow = put_row_RGB_565;
@@ -678,7 +954,6 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
rb->GreenBits = 6;
rb->BlueBits = 5;
}
-#endif
else if (osmesa->format == OSMESA_COLOR_INDEX) {
rb->GetRow = get_row_CI;
rb->GetValues = get_values_CI;
@@ -692,33 +967,36 @@ osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
_mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
}
+ rb->Width = width;
+ rb->Height = height;
+
return GL_TRUE;
}
/**
- * Allocate a new renderbuffer tpo describe the user-provided color buffer.
+ * Allocate a new renderbuffer to describe the user-provided color buffer.
*/
static struct gl_renderbuffer *
-new_osmesa_renderbuffer(GLenum format)
+new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type)
{
- struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
+ const GLuint name = 0;
+ struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
if (rb) {
- const GLuint name = 0;
- _mesa_init_renderbuffer(rb, name);
-
rb->Delete = osmesa_delete_renderbuffer;
rb->AllocStorage = osmesa_renderbuffer_storage;
if (format == OSMESA_COLOR_INDEX) {
- rb->_BaseFormat = GL_COLOR_INDEX;
rb->InternalFormat = GL_COLOR_INDEX;
+ rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
+ rb->_BaseFormat = GL_COLOR_INDEX;
rb->DataType = GL_UNSIGNED_BYTE;
}
else {
- rb->_BaseFormat = GL_RGBA;
rb->InternalFormat = GL_RGBA;
- rb->DataType = CHAN_TYPE;
+ rb->_ActualFormat = GL_RGBA;
+ rb->_BaseFormat = GL_RGBA;
+ rb->DataType = type;
}
}
return rb;
@@ -726,12 +1004,70 @@ new_osmesa_renderbuffer(GLenum format)
+/**
+ * Recompute the values of the context's rowaddr array.
+ */
+static void
+compute_row_addresses( OSMesaContext osmesa )
+{
+ GLint bytesPerPixel, bytesPerRow, i;
+ GLubyte *origin = (GLubyte *) osmesa->rb->Data;
+ GLint bpc; /* bytes per channel */
+
+ if (osmesa->rb->DataType == GL_UNSIGNED_BYTE)
+ bpc = 1;
+ else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT)
+ bpc = 2;
+ else if (osmesa->rb->DataType == GL_FLOAT)
+ bpc = 4;
+ else {
+ _mesa_problem(&osmesa->mesa,
+ "Unexpected datatype in osmesa::compute_row_addresses");
+ return;
+ }
+
+ if (osmesa->format == OSMESA_COLOR_INDEX) {
+ /* CI mode */
+ bytesPerPixel = 1 * sizeof(GLubyte);
+ }
+ else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) {
+ /* RGB mode */
+ bytesPerPixel = 3 * bpc;
+ }
+ else if (osmesa->format == OSMESA_RGB_565) {
+ /* 5/6/5 RGB pixel in 16 bits */
+ bytesPerPixel = 2;
+ }
+ else {
+ /* RGBA mode */
+ bytesPerPixel = 4 * bpc;
+ }
+
+ bytesPerRow = osmesa->rowlength * bytesPerPixel;
+
+ if (osmesa->yup) {
+ /* Y=0 is bottom line of window */
+ for (i = 0; i < MAX_HEIGHT; i++) {
+ osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
+ }
+ }
+ else {
+ /* Y=0 is top line of window */
+ for (i = 0; i < MAX_HEIGHT; i++) {
+ GLint j = osmesa->height - i - 1;
+ osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
+ }
+ }
+}
+
+
+
/**********************************************************************/
/***** Public Functions *****/
/**********************************************************************/
-/*
+/**
* Create an Off-Screen Mesa rendering context. The only attribute needed is
* an RGBA vs Color-Index mode flag.
*
@@ -750,7 +1086,7 @@ OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
-/*
+/**
* New in Mesa 3.5
*
* Create context and specify size of ancillary buffers.
@@ -764,6 +1100,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
GLint rind, gind, bind, aind;
GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
GLboolean rgbmode;
+ GLenum type = CHAN_TYPE;
rind = gind = bind = aind = 0;
if (format==OSMESA_COLOR_INDEX) {
@@ -864,7 +1201,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
1 /* num samples */
);
if (!osmesa->gl_visual) {
- FREE(osmesa);
+ _mesa_free(osmesa);
return NULL;
}
@@ -881,7 +1218,7 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
: (GLcontext *) NULL,
&functions, (void *) osmesa)) {
_mesa_destroy_visual( osmesa->gl_visual );
- FREE(osmesa);
+ _mesa_free(osmesa);
return NULL;
}
@@ -894,13 +1231,14 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
if (!osmesa->gl_buffer) {
_mesa_destroy_visual( osmesa->gl_visual );
_mesa_free_context_data( &osmesa->mesa );
- FREE(osmesa);
+ _mesa_free(osmesa);
return NULL;
}
/* create front color buffer in user-provided memory (no back buffer) */
- _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
- new_osmesa_renderbuffer(format));
+ osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type);
+ _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
+
_mesa_add_soft_renderbuffers(osmesa->gl_buffer,
GL_FALSE, /* color */
osmesa->gl_visual->haveDepthBuffer,
@@ -910,7 +1248,6 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
GL_FALSE /* aux */ );
osmesa->format = format;
- osmesa->buffer = NULL;
osmesa->width = 0;
osmesa->height = 0;
osmesa->userRowLength = 0;
@@ -955,73 +1292,29 @@ OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
}
-/*
+/**
* Destroy an Off-Screen Mesa rendering context.
*
- * Input: ctx - the context to destroy
+ * \param osmesa the context to destroy
*/
GLAPI void GLAPIENTRY
-OSMesaDestroyContext( OSMesaContext ctx )
-{
- if (ctx) {
- _swsetup_DestroyContext( &ctx->mesa );
- _tnl_DestroyContext( &ctx->mesa );
- _ac_DestroyContext( &ctx->mesa );
- _swrast_DestroyContext( &ctx->mesa );
-
- _mesa_destroy_visual( ctx->gl_visual );
- _mesa_destroy_framebuffer( ctx->gl_buffer );
- _mesa_free_context_data( &ctx->mesa );
- FREE( ctx );
- }
-}
-
-
-/*
- * Recompute the values of the context's rowaddr array.
- */
-static void
-compute_row_addresses( OSMesaContext ctx )
+OSMesaDestroyContext( OSMesaContext osmesa )
{
- GLint bytesPerPixel, bytesPerRow, i;
- GLubyte *origin = (GLubyte *) ctx->buffer;
-
- if (ctx->format == OSMESA_COLOR_INDEX) {
- /* CI mode */
- bytesPerPixel = 1 * sizeof(GLubyte);
- }
- else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
- /* RGB mode */
- bytesPerPixel = 3 * sizeof(GLchan);
- }
- else if (ctx->format == OSMESA_RGB_565) {
- /* 5/6/5 RGB pixel in 16 bits */
- bytesPerPixel = 2;
- }
- else {
- /* RGBA mode */
- bytesPerPixel = 4 * sizeof(GLchan);
- }
-
- bytesPerRow = ctx->rowlength * bytesPerPixel;
-
- if (ctx->yup) {
- /* Y=0 is bottom line of window */
- for (i = 0; i < MAX_HEIGHT; i++) {
- ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
- }
- }
- else {
- /* Y=0 is top line of window */
- for (i = 0; i < MAX_HEIGHT; i++) {
- GLint j = ctx->height - i - 1;
- ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
- }
+ if (osmesa) {
+ _swsetup_DestroyContext( &osmesa->mesa );
+ _tnl_DestroyContext( &osmesa->mesa );
+ _ac_DestroyContext( &osmesa->mesa );
+ _swrast_DestroyContext( &osmesa->mesa );
+
+ _mesa_destroy_visual( osmesa->gl_visual );
+ _mesa_destroy_framebuffer( osmesa->gl_buffer );
+ _mesa_free_context_data( &osmesa->mesa );
+ _mesa_free( osmesa );
}
}
-/*
+/**
* 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
@@ -1034,33 +1327,37 @@ compute_row_addresses( OSMesaContext ctx )
* 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
+ * Input: osmesa - the rendering context
* buffer - the image buffer memory
* type - data type for pixel components
* Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
* are supported. But if Mesa's been compiled with CHAN_BITS==16
- * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build
- * with CHAN_BITS==32 then type must be GL_FLOAT.
+ * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if
+ * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
+ * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
* width, height - size of image buffer in pixels, at least 1
- * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
+ * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
* invalid buffer address, invalid type, width<1, height<1,
* width>internal limit or height>internal limit.
*/
GLAPI GLboolean GLAPIENTRY
-OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
+OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
GLsizei width, GLsizei height )
{
- if (!ctx || !buffer ||
+ if (!osmesa || !buffer ||
width < 1 || height < 1 ||
width > MAX_WIDTH || height > MAX_HEIGHT) {
return GL_FALSE;
}
- if (ctx->format == OSMESA_RGB_565) {
- if (type != GL_UNSIGNED_SHORT_5_6_5)
- return GL_FALSE;
+ if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
+ return GL_FALSE;
}
- else if (type != CHAN_TYPE) {
+
+ if (!(type == GL_UNSIGNED_BYTE ||
+ (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
+ (type == GL_FLOAT && CHAN_BITS == 32))) {
+ /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
return GL_FALSE;
}
@@ -1069,28 +1366,43 @@ OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
* get_buffer_size() function to initialize the viewport. These are the
* values returned by get_buffer_size():
*/
- ctx->buffer = buffer;
- ctx->width = width;
- ctx->height = height;
+ osmesa->width = width;
+ osmesa->height = height;
- osmesa_update_state( &ctx->mesa, 0 );
+ osmesa_update_state( &osmesa->mesa, 0 );
/* Call this periodically to detect when the user has begun using
* GL rendering from multiple threads.
*/
_glapi_check_multithread();
- _mesa_make_current( &ctx->mesa, ctx->gl_buffer, ctx->gl_buffer );
+ _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
- if (ctx->userRowLength)
- ctx->rowlength = ctx->userRowLength;
+ if (osmesa->userRowLength)
+ osmesa->rowlength = osmesa->userRowLength;
else
- ctx->rowlength = width;
+ osmesa->rowlength = width;
+
+ osmesa->rb->Data = buffer;
+ osmesa->rb->DataType = type;
+ compute_row_addresses( osmesa );
+
+ /* update the color renderbuffer's format, type, width, height */
+ osmesa_renderbuffer_storage(&osmesa->mesa, osmesa->rb,
+ osmesa->rb->InternalFormat, width, height);
- compute_row_addresses( ctx );
+ /* Remove renderbuffer attachment, then re-add. This installs the
+ * renderbuffer adaptor/wrapper if needed.
+ */
+ _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
+ _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
- /* this will make ensure we recognize the new buffer size */
- _mesa_resize_framebuffer(&ctx->mesa, ctx->gl_buffer, width, height);
+
+ /* this updates the visual's red/green/blue/alphaBits fields */
+ _mesa_update_framebuffer_visual(osmesa->gl_buffer);
+
+ /* update the framebuffer size */
+ _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
return GL_TRUE;
}
@@ -1152,7 +1464,13 @@ OSMesaGetIntegerv( GLint pname, GLint *value )
*value = osmesa->format;
return;
case OSMESA_TYPE:
- *value = CHAN_TYPE;
+ /* current color buffer's data type */
+ if (osmesa->rb) {
+ *value = osmesa->rb->DataType;
+ }
+ else {
+ *value = 0;
+ }
return;
case OSMESA_ROW_LENGTH:
*value = osmesa->userRowLength;
@@ -1172,7 +1490,8 @@ OSMesaGetIntegerv( GLint pname, GLint *value )
}
}
-/*
+
+/**
* Return the depth buffer associated with an OSMesa context.
* Input: c - the OSMesa context
* Output: width, height - size of buffer in pixels
@@ -1190,7 +1509,6 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
if (!rb || !rb->Data) {
- /*if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {*/
*width = 0;
*height = 0;
*bytesPerValue = 0;
@@ -1209,7 +1527,8 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
}
}
-/*
+
+/**
* Return the color buffer associated with an OSMesa context.
* Input: c - the OSMesa context
* Output: width, height - size of buffer in pixels
@@ -1218,23 +1537,23 @@ OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
* Return: GL_TRUE or GL_FALSE to indicate success or failure.
*/
GLAPI GLboolean GLAPIENTRY
-OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
+OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
GLint *height, GLint *format, void **buffer )
{
- if (!c->buffer) {
+ if (osmesa->rb && osmesa->rb->Data) {
+ *width = osmesa->rb->Width;
+ *height = osmesa->rb->Height;
+ *format = osmesa->format;
+ *buffer = osmesa->rb->Data;
+ return GL_TRUE;
+ }
+ else {
*width = 0;
*height = 0;
*format = 0;
*buffer = 0;
return GL_FALSE;
}
- else {
- *width = c->width;
- *height = c->height;
- *format = c->format;
- *buffer = c->buffer;
- return GL_TRUE;
- }
}
diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c
index 09330e78ab5..ca79ebb6c74 100644
--- a/src/mesa/drivers/svga/svgamesa.c
+++ b/src/mesa/drivers/svga/svgamesa.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa.c,v 1.26 2005/09/07 23:26:01 brianp Exp $ */
+/* $Id: svgamesa.c,v 1.26 2005-09-07 23:26:01 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa15.c b/src/mesa/drivers/svga/svgamesa15.c
index 54b6c977a7b..817da34ef1d 100644
--- a/src/mesa/drivers/svga/svgamesa15.c
+++ b/src/mesa/drivers/svga/svgamesa15.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa15.c,v 1.11 2002/11/11 18:42:39 brianp Exp $ */
+/* $Id: svgamesa15.c,v 1.11 2002-11-11 18:42:39 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa15.h b/src/mesa/drivers/svga/svgamesa15.h
index 3ed7db82ee5..4a318d3aa73 100644
--- a/src/mesa/drivers/svga/svgamesa15.h
+++ b/src/mesa/drivers/svga/svgamesa15.h
@@ -1,4 +1,4 @@
-/* $Id: svgamesa15.h,v 1.7 2002/11/11 18:42:39 brianp Exp $ */
+/* $Id: svgamesa15.h,v 1.7 2002-11-11 18:42:39 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa16.c b/src/mesa/drivers/svga/svgamesa16.c
index 72ac8183294..483158ccdb4 100644
--- a/src/mesa/drivers/svga/svgamesa16.c
+++ b/src/mesa/drivers/svga/svgamesa16.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa16.c,v 1.11 2002/11/11 18:42:40 brianp Exp $ */
+/* $Id: svgamesa16.c,v 1.11 2002-11-11 18:42:40 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa16.h b/src/mesa/drivers/svga/svgamesa16.h
index 247c1f40455..91ac404ab77 100644
--- a/src/mesa/drivers/svga/svgamesa16.h
+++ b/src/mesa/drivers/svga/svgamesa16.h
@@ -1,4 +1,4 @@
-/* $Id: svgamesa16.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */
+/* $Id: svgamesa16.h,v 1.6 2002-11-11 18:42:41 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa24.c b/src/mesa/drivers/svga/svgamesa24.c
index 07491cc67ac..ff3b24894e1 100644
--- a/src/mesa/drivers/svga/svgamesa24.c
+++ b/src/mesa/drivers/svga/svgamesa24.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa24.c,v 1.12 2002/11/11 18:42:41 brianp Exp $ */
+/* $Id: svgamesa24.c,v 1.12 2002-11-11 18:42:41 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa24.h b/src/mesa/drivers/svga/svgamesa24.h
index 54d1a8298ba..be41bd4abb5 100644
--- a/src/mesa/drivers/svga/svgamesa24.h
+++ b/src/mesa/drivers/svga/svgamesa24.h
@@ -1,4 +1,4 @@
-/* $Id: svgamesa24.h,v 1.6 2002/11/11 18:42:41 brianp Exp $ */
+/* $Id: svgamesa24.h,v 1.6 2002-11-11 18:42:41 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa32.c b/src/mesa/drivers/svga/svgamesa32.c
index 8a366998d6b..a7829526dda 100644
--- a/src/mesa/drivers/svga/svgamesa32.c
+++ b/src/mesa/drivers/svga/svgamesa32.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa32.c,v 1.12 2002/11/11 18:42:42 brianp Exp $ */
+/* $Id: svgamesa32.c,v 1.12 2002-11-11 18:42:42 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa32.h b/src/mesa/drivers/svga/svgamesa32.h
index f518e11ad5b..f622fbfa64b 100644
--- a/src/mesa/drivers/svga/svgamesa32.h
+++ b/src/mesa/drivers/svga/svgamesa32.h
@@ -1,4 +1,4 @@
-/* $Id: svgamesa32.h,v 1.6 2002/11/11 18:42:42 brianp Exp $ */
+/* $Id: svgamesa32.h,v 1.6 2002-11-11 18:42:42 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa8.c b/src/mesa/drivers/svga/svgamesa8.c
index fd880ef85ad..6f57ae7e4d6 100644
--- a/src/mesa/drivers/svga/svgamesa8.c
+++ b/src/mesa/drivers/svga/svgamesa8.c
@@ -1,4 +1,4 @@
-/* $Id: svgamesa8.c,v 1.9 2005/05/04 20:11:39 brianp Exp $ */
+/* $Id: svgamesa8.c,v 1.9 2005-05-04 20:11:39 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgamesa8.h b/src/mesa/drivers/svga/svgamesa8.h
index 1aa25f93fce..d9c1979f0e0 100644
--- a/src/mesa/drivers/svga/svgamesa8.h
+++ b/src/mesa/drivers/svga/svgamesa8.h
@@ -1,4 +1,4 @@
-/* $Id: svgamesa8.h,v 1.4 2001/02/06 00:03:48 brianp Exp $ */
+/* $Id: svgamesa8.h,v 1.4 2001-02-06 00:03:48 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/svga/svgapix.h b/src/mesa/drivers/svga/svgapix.h
index 0b19551bf6e..00c1292bb3a 100644
--- a/src/mesa/drivers/svga/svgapix.h
+++ b/src/mesa/drivers/svga/svgapix.h
@@ -1,4 +1,4 @@
-/* $Id: svgapix.h,v 1.5 2002/11/11 18:42:44 brianp Exp $ */
+/* $Id: svgapix.h,v 1.5 2002-11-11 18:42:44 brianp Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/windows/fx/fx.rc b/src/mesa/drivers/windows/fx/fx.rc
new file mode 100644
index 00000000000..f920b8768dd
--- /dev/null
+++ b/src/mesa/drivers/windows/fx/fx.rc
@@ -0,0 +1,39 @@
+#include <windows.h>
+
+#define PRODNAME "Mesa 6.x"
+#define CONTACTSTR "http://www.mesa3d.org"
+#define HWSTR "3dfx Voodoo Graphics, Voodoo Rush, Voodoo^2, Voodoo Banshee, Velocity 100/200, Voodoo3, Voodoo4, Voodoo5"
+#define COPYRIGHTSTR "Copyright \251 Brian E. Paul"
+
+#define VERSIONSTR "6.3.0.1"
+#define MANVERSION 6
+#define MANREVISION 3
+#define BUILD_NUMBER 1
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER
+ PRODUCTVERSION MANVERSION, MANREVISION, 0, BUILD_NUMBER
+ FILEFLAGSMASK 0x0030003FL
+
+ FILEOS VOS_DOS_WINDOWS32
+ FILETYPE VFT_DRV
+ FILESUBTYPE VFT2_DRV_INSTALLABLE
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "FileDescription", PRODNAME
+ VALUE "FileVersion", VERSIONSTR
+ VALUE "LegalCopyright", COPYRIGHTSTR
+ VALUE "ProductName", PRODNAME
+ VALUE "Graphics Subsystem", HWSTR
+ VALUE "Contact", CONTACTSTR
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* the following line should be extended for localized versions */
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/src/mesa/drivers/windows/gdi/wgl.c b/src/mesa/drivers/windows/gdi/wgl.c
index 197de0743c7..2eef039d5d8 100644
--- a/src/mesa/drivers/windows/gdi/wgl.c
+++ b/src/mesa/drivers/windows/gdi/wgl.c
@@ -1,4 +1,4 @@
-/* $Id: wgl.c,v 1.12 2006/03/30 07:58:24 kschultz Exp $ */
+/* $Id: wgl.c,v 1.12 2006-03-30 07:58:24 kschultz Exp $ */
/*
* This library is free software; you can redistribute it and/or
diff --git a/src/mesa/drivers/windows/gdi/wmesa.c b/src/mesa/drivers/windows/gdi/wmesa.c
index 21292494242..8e861da5081 100644
--- a/src/mesa/drivers/windows/gdi/wmesa.c
+++ b/src/mesa/drivers/windows/gdi/wmesa.c
@@ -782,7 +782,7 @@ static void read_rgba_pixels_32(const GLcontext *ctx,
for (i=0; i<n; i++) {
GLint y2 = FLIP(y[i]);
lpdw = ((LPDWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
- pixel = lpdw[i];
+ pixel = *lpdw;
rgba[i][RCOMP] = (pixel & 0x00ff0000) >> 16;
rgba[i][GCOMP] = (pixel & 0x0000ff00) >> 8;
rgba[i][BCOMP] = (pixel & 0x000000ff);
@@ -966,7 +966,7 @@ static void read_rgba_pixels_16(const GLcontext *ctx,
for (i=0; i<n; i++) {
GLint y2 = FLIP(y[i]);
lpw = ((LPWORD)(pwfb->pbPixels + pwfb->ScanWidth * y2)) + x[i];
- pixel = lpw[i];
+ pixel = *lpw;
/* Windows uses 5,5,5 for 16-bit */
rgba[i][RCOMP] = (pixel & 0x7c00) >> 7;
rgba[i][GCOMP] = (pixel & 0x03e0) >> 2;
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
new file mode 100644
index 00000000000..cad299540d7
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
@@ -0,0 +1,1196 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX7(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX7(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX7(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX7(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX7(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+// ctx->Color.ClearColor[1],
+// ctx->Color.ClearColor[2],
+// ctx->Color.ClearColor[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D7 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX7_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX7(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX7(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX7(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SRCBLEND, src));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_DESTBLEND, dest));
+
+/*
+ // Color mask - unsupported by DX7
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_COLORWRITEENABLE, dwFlags));
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ int iOffset = 0;
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ iOffset = (int)ctx->Polygon.OffsetUnits;
+ if (iOffset < 0)
+ iOffset = -iOffset;
+ else
+ iOffset = 0; // D3D can't push away
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZBIAS, iOffset));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+/* m[0][0] = pM[0];
+ m[0][1] = pM[1];
+ m[0][2] = pM[2];
+ m[0][3] = pM[3];
+ m[1][0] = pM[4];
+ m[1][1] = pM[5];
+ m[1][2] = pM[6];
+ m[1][3] = pM[7];
+ m[2][0] = pM[8];
+ m[2][1] = pM[9];
+ m[2][2] = pM[10];
+ m[2][3] = pM[11];
+ m[3][0] = pM[12];
+ m[3][1] = pM[13];
+ m[3][2] = pM[14];
+ m[3][3] = pM[15];*/
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX7(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX7(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DVIEWPORT7 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX7_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.dvMinZ = ctx->Viewport.Near;
+ d3dvp.dvMaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.dvMinZ = ctx->Viewport.Far;
+ d3dvp.dvMaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx7 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX7(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx7 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, TRUE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, FALSE));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+ // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX7(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX7(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX7(_NEW_TEXTURE); // extern, so guard with _DX7
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX7(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DVIEWPORT7 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.dwX = x;
+ d3dvp.dwY = gldCtx->dwHeight - (y + h);
+ d3dvp.dwWidth = w;
+ d3dvp.dwHeight = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.dvMinZ = ctx->Viewport.Near;
+ d3dvp.dvMaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.dvMinZ = ctx->Viewport.Far;
+ d3dvp.dvMaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX7(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX7(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX7;
+ ctx->Driver.Clear = gld_Clear_DX7;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX7;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX7;
+ ctx->Driver.Finish = gld_Finish_DX7;
+ ctx->Driver.Flush = gld_Flush_DX7;
+ ctx->Driver.Error = gld_Error_DX7;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX7;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX7;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX7;
+ ctx->Driver.Bitmap = gld_Bitmap_DX7;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX7;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX7;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX7;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX7;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX7;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX7;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX7; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX7;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX7;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX7;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX7;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX7;
+// ctx->Exec->Ortho = gldOrthoHook_DX7;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h
new file mode 100644
index 00000000000..b5a491e41b1
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 7.0a header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX7_H
+#define _GLD_DX7_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+#define DIRECTDRAW_VERSION 0x0700
+#define DIRECT3D_VERSION 0x0700
+#include <d3d.h>
+#include <d3dx.h>
+
+// Typedef for obtaining function from d3d7.dll
+//typedef IDirect3D7* (WINAPI *FNDIRECT3DCREATE7) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+// Debug build tests the return value of D3D calls
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX7(func) _GLD_TEST_HRESULT(IDirect3D7_##func##)
+#define _GLD_DX7_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice7_##func##)
+#define _GLD_DX7_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer7_##func##)
+#define _GLD_DX7_TEX(func) _GLD_TEST_HRESULT(IDirectDrawSurface7_##func##)
+#else
+#define _GLD_DX7(func) IDirect3D7_##func
+#define _GLD_DX7_DEV(func) IDirect3DDevice7_##func
+#define _GLD_DX7_VB(func) IDirect3DVertexBuffer7_##func
+#define _GLD_DX7_TEX(func) IDirectDrawSurface7_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB7(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer7_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE7(p) \
+{ \
+ if (p) { \
+ IDirectDrawSurface7_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Emulate some DX8 defines
+#define D3DCOLOR_ARGB(a,r,g,b) ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
+#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b)
+#define D3DCOLOR_COLORVALUE(r,g,b,a) D3DCOLOR_RGBA((DWORD)((r)*255.f),(DWORD)((g)*255.f),(DWORD)((b)*255.f),(DWORD)((a)*255.f))
+
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX7 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3D7::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwCreateFlags; // Create flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+
+ IDirect3DVertexBuffer7 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx7;
+
+// GLDirect DX7 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DX_SURFACEFORMAT RenderFormat; // Format of back/front buffer
+ D3DX_SURFACEFORMAT DepthFormat; // Format of depth/stencil
+
+ // Direct3D vars
+ DDCAPS ddCaps;
+ D3DDEVICEDESC7 d3dCaps;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ ID3DXContext *pD3DXContext; // Base D3DX context
+ IDirectDraw7 *pDD; // DirectDraw7 interface
+ IDirect3D7 *pD3D; // Base Direct3D7 interface
+ IDirect3DDevice7 *pDev; // Direct3D7 Device interface
+ GLD_pb_dx7 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx7 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ GLD_pipeline_usage PipelineUsage;
+} GLD_driver_dx7;
+
+#define GLD_GET_DX7_DRIVER(c) (GLD_driver_dx7*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX7(LPCSTR a);
+void gldEnableExtensions_DX7(GLcontext *ctx);
+void gldInstallPipeline_DX7(GLcontext *ctx);
+void gldSetupDriverPointers_DX7(GLcontext *ctx);
+void gldResizeBuffers_DX7(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX7(GLcontext *ctx);
+void gld_DrawPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX7(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX7(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX7(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX7(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX7(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX7(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX7(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h
new file mode 100644
index 00000000000..df6fceb43e6
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr8.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR7_H_
+#define _GLD_DXERR7_H_
+
+
+#include <d3d.h>
+
+//
+// DXGetErrorString8
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString8A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString8 DXGetErrorString8W
+#else
+ #define DXGetErrorString8 DXGetErrorString8A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c
new file mode 100644
index 00000000000..6be41a80dd3
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c
@@ -0,0 +1,346 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#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)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX7(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ "GL_EXT_abgr",
+ "GL_EXT_bgra",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c
new file mode 100644
index 00000000000..9ccec69b98a
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct tnl_pipeline_stage _gld_d3d_render_stage;
+extern struct tnl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct tnl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX7(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
new file mode 100644
index 00000000000..5da25003c08
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
@@ -0,0 +1,1448 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX7(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX7(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ // Not supported by DX7
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX7(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ // Not supported by DX7
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c
new file mode 100644
index 00000000000..bbe673516d6
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c
@@ -0,0 +1,2196 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//#include <d3dx8tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface(IDirectDrawSurface7 *pSurface);
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ //
+ // DX7 Does not support D3DTOP_LERP
+ // Emulate(?) via D3DTOP_ADDSMOOTH
+ //
+#if 0
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+#else
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+#endif
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+// ASSERT(wrap==GL_CLAMP || wrap==GL_REPEAT);
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREMAGFILTER _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ ASSERT(magfilter==GL_LINEAR || magfilter==GL_NEAREST);
+ return (magfilter == GL_LINEAR) ? D3DTFG_LINEAR : D3DTFG_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREMINFILTER *min_filter,
+ D3DTEXTUREMIPFILTER *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_LINEAR;
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DX_SF_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DX_SF_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DX_SF_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DX_SF_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DX_SF_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DX_SF_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DX_SF_X4R4G4B4;
+ case GL_RGB5:
+ return D3DX_SF_R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DX_SF_R8G8B8;
+ case GL_RGBA4:
+ return D3DX_SF_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DX_SF_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DX_SF_A1R5G5B5;
+ }
+
+ ASSERT(0);
+
+ // Return an acceptable default
+ return D3DX_SF_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirectDrawSurface7 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+// D3DSURFACE_DESC desc;
+// _GLD_DX7_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ D3DX_SURFACEFORMAT sf;
+
+ sf = _gldD3DXFormatFromSurface(pTex);
+
+ switch (sf) {
+ case D3DX_SF_R8G8B8:
+ case D3DX_SF_X8R8G8B8:
+ case D3DX_SF_R5G6B5:
+ case D3DX_SF_R5G5B5:
+ case D3DX_SF_R3G3B2:
+ case D3DX_SF_X4R4G4B4:
+ case D3DX_SF_PALETTE8:
+ case D3DX_SF_L8:
+ return GL_RGB;
+ case D3DX_SF_A8R8G8B8:
+ case D3DX_SF_A1R5G5B5:
+ case D3DX_SF_A4R4G4B4:
+// case D3DX_SF_A8R3G3B2: // Unsupported by DX7
+// case D3DX_SF_A8P8: // Unsupported by DX7
+ case D3DX_SF_A8L8:
+// case D3DX_SF_A4L4: // Unsupported by DX7
+ return GL_RGBA;
+ case D3DX_SF_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DX_SF_DXT1:
+ return GL_RGBA;
+// case D3DX_SF_DXT2: // Unsupported by DX7
+ return GL_RGB;
+ case D3DX_SF_DXT3:
+ return GL_RGBA;
+// case D3DX_SF_DXT4: // Unsupported by DX7
+ return GL_RGB;
+ case D3DX_SF_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ ASSERT(0); // BANG!
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DX_SURFACEFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DX_SF_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DX_SF_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DX_SF_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DX_SF_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DX_SF_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DX_SF_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DX_SF_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DX_SF_A8:
+ return &_mesa_texformat_a8;
+ case D3DX_SF_L8:
+ return &_mesa_texformat_l8;
+ case D3DX_SF_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DX_SF_R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DX_SF_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ ASSERT(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface(
+ IDirectDrawSurface7 *pSurface)
+{
+ DDPIXELFORMAT ddpf;
+
+ ddpf.dwSize = sizeof(ddpf);
+
+ // Obtain pixel format of surface
+ _GLD_DX7_TEX(GetPixelFormat(pSurface, &ddpf));
+ // Decode to D3DX surface format
+ return D3DXMakeSurfaceFormat(&ddpf);
+}
+
+//---------------------------------------------------------------------------
+
+void _gldClearSurface(
+ IDirectDrawSurface *pSurface,
+ D3DCOLOR dwColour)
+{
+ DDBLTFX bltFX; // Used for colour fill
+
+ // Initialise struct
+ bltFX.dwSize = sizeof(bltFX);
+ // Set clear colour
+ bltFX.dwFillColor = dwColour;
+ // Clear surface. HW accelerated if available.
+ IDirectDrawSurface7_Blt(pSurface, NULL, NULL, NULL, DDBLT_COLORFILL, &bltFX);
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX7(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX7(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirectDrawSurface7 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ // NOTE: This DX7 version does not create a new texture in which
+ // to copy the input image, as the image is already a texture.
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DDSURFACEDESC2 ddsd;
+ _GLD_IMAGE_VERTEX v[4];
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Fixup for rasterisation rules
+ const float cfEpsilon = 1.0f / (float)height;
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ IDirectDrawSurface7_GetSurfaceDesc(pImage, &ddsd);
+ ScaleWidth = (float)width / (float)ddsd.dwWidth;
+ ScaleHeight = (float)height / (float)ddsd.dwHeight;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y+cfEpsilon);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y+cfEpsilon);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice7_SetTexture(gld->pDev, 0, pImage);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTFN_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTFP_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTFG_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ // Ensure texture unit 1 is disabled
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice7_DrawPrimitive(gld->pDev, D3DPT_TRIANGLEFAN, _GLD_FVF_IMAGE, &v, 4, 0);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX7(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirectDrawSurface7 *pImage;
+ HRESULT hr;
+ DDSURFACEDESC2 ddsd;
+ DWORD dwFlags;
+ D3DX_SURFACEFORMAT sf;
+ DWORD dwMipmaps;
+
+ const struct gl_texture_format *MesaFormat;
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ dwFlags = D3DX_TEXTURE_NOMIPMAP;
+ sf = D3DX_SF_A8R8G8B8;
+ dwMipmaps = 1;
+
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &width, &height,
+ &sf, // format
+ NULL, // palette
+ &pImage, // Output texture
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // D3DXCreateTexture() may not clear the texture is creates.
+ _gldClearSurface(pImage, 0);
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT;
+ hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL);
+ if (FAILED(hr)) {
+ SAFE_RELEASE_SURFACE7(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ ddsd.lpSurface,
+ width, height, 1, 0, 0, 0,
+ ddsd.lPitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirectDrawSurface7_Unlock(pImage, NULL);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ SAFE_RELEASE_SURFACE7(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX7(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+// TODO
+#if 0
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirect3DSurface8 *pBackbuffer = NULL;
+ IDirect3DSurface8 *pNativeImage = NULL;
+ IDirect3DSurface8 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pNativeImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pCanonicalImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface8_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX7_return:
+ SAFE_RELEASE_SURFACE8(pCanonicalImage);
+ SAFE_RELEASE_SURFACE8(pNativeImage);
+ SAFE_RELEASE_SURFACE8(pBackbuffer);
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX7(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+// TODO
+#if 0
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirect3DSurface8 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pImage);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);
+ IDirect3DSurface8_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX7(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirectDrawSurface7 *pImage; // Bitmap texture
+ HRESULT hr;
+ BYTE *pTempBitmap; // Pointer to unpacked bitmap
+ D3DCOLOR clBitmapOne; // Opaque bitmap colour
+ D3DCOLOR clBitmapZero; // Transparent bitmap colour
+ D3DCOLOR *pBits; // Pointer to texture surface
+ const GLubyte *src;
+ int i, j, k;
+
+ DDSURFACEDESC2 ddsd; // Surface desc returned by lock call
+ DWORD dwFlags;
+ D3DX_SURFACEFORMAT sf;
+ DWORD dwMipmaps;
+
+ // Keep a copy of width/height as D3DXCreateTexture() call may alter input dimensions
+ GLsizei dwWidth = width;
+ GLsizei dwHeight = height;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Bail if no bitmap (only raster pos is updated)
+ if ((bitmap == NULL) && (width==0) && (height==0))
+ return;
+
+ //
+ // TODO: Detect conditions when created texture (pImage) is non-pow2.
+ // Texture coords may need to be adjusted to compensate.
+ //
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ // Use Mesa to unpack bitmap into a canonical format
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL)
+ return;
+
+ // Flags for texture creation
+ dwFlags = D3DX_TEXTURE_NOMIPMAP;
+ sf = D3DX_SF_A8R8G8B8;
+ dwMipmaps = 1;
+
+ // Create a D3D texture to hold the bitmap
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &dwWidth, &dwHeight,
+ &sf, // format
+ NULL, // palette
+ &pImage, // Output texture
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ FREE(pTempBitmap);
+ return;
+ }
+
+ // D3DXCreateTexture may return a texture bigger than we asked for
+ // (i.e. padded to POW2) so let's clear the entire image bitmap.
+ // Additional: Looks like this is not strictly necessary.
+// _gldClearSurface(pImage, clBitmapZero);
+
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT;
+ hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL);
+ if (FAILED(hr)) {
+ FREE(pTempBitmap);
+ SAFE_RELEASE_SURFACE7(pImage);
+ return;
+ }
+
+#if 0
+ // DEBUG CODE
+ if (!(width==ddsd.dwWidth && height==ddsd.dwHeight))
+ ddlogPrintf(GLDLOG_WARN, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight);
+#endif
+
+#if 0
+ // DEBUG CODE
+ ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight);
+ ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: bpp=%d", ddsd.ddpfPixelFormat.dwRGBBitCount);
+#endif
+
+ // Cast texel pointer to texture surface.
+ // We can do this because we used D3DX_SF_A8R8G8B8 as the format
+ pBits = (D3DCOLOR*)ddsd.lpSurface;
+
+
+ // Copy from the input bitmap into the texture
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)ddsd.lpSurface + (i*ddsd.lPitch));
+ src = (const GLubyte *) _mesa_image_address(2,
+ &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ // We're done with the unpacked bitmap
+ FREE(pTempBitmap);
+
+ // Finished with texture surface - unlock it
+ IDirectDrawSurface7_Unlock(pImage, NULL);
+
+ // Use internal function to draw bitmap onto rendertarget
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ // We're done with the bitmap texure - release it
+ IDirectDrawSurface7_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ HRESULT hr;
+ IDirectDrawSurface7 *pTex;
+ D3DX_SURFACEFORMAT d3dFormat;
+ DWORD dwFlags;
+ DWORD dwMipmaps;
+ DWORD dwWidth, dwHeight;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ // Release existing texture if not compatible
+ if ((ddsd.dwWidth == texImage->Width) ||
+ (ddsd.dwHeight == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX7_TEX(Release(pTex));
+ }
+
+ dwFlags = (glb.bUseMipmaps) ? 0 : D3DX_TEXTURE_NOMIPMAP;
+ dwMipmaps = (glb.bUseMipmaps) ? D3DX_DEFAULT : 1;
+ dwWidth = texImage->Width;
+ dwHeight = texImage->Height;
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &dwWidth,
+ &dwHeight,
+ &d3dFormat,
+ NULL,
+ &pTex,
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ gldLogError(GLDLOG_ERROR, "AllocateTexture failed", hr);
+ }
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX7(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirectDrawSurface7 *pTex = NULL;
+ IDirectDrawSurface7 *pSurface = NULL;
+ HRESULT hr;
+ DDSURFACEDESC2 ddsd;
+ int i;
+ DDSCAPS2 ddsCaps;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (!pTex) {
+ ASSERT(0);
+ return; // Texture has not been created
+ }
+
+ pSurface = pTex;
+ if (level != 0) {
+ ddsd.dwSize = sizeof(ddsd);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ if ((level > 0) && (level >= ddsd.dwMipMapCount))
+ return; // Level does not exist
+ ZeroMemory(&ddsCaps, sizeof(ddsCaps));
+ for (i=0; i<level; i++) {
+ ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+ hr = IDirectDrawSurface7_GetAttachedSurface(
+ pSurface,
+ &ddsCaps,
+ &pSurface);
+ if (SUCCEEDED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ } else {
+ ;
+ }
+ }
+ }
+
+ // Lock all of surface
+ ddsd.dwSize = sizeof(ddsd);
+ hr = IDirectDrawSurface7_Lock(pSurface, NULL, &ddsd, 0, 0);
+ if (FAILED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ texImage->Format,
+ //_gldMesaFormatForD3DFormat(d3dsd.Format),
+ _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)),
+ ddsd.lpSurface,
+ width, height, 1, 0, 0, 0,
+ ddsd.lPitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirectDrawSurface7_Unlock(pSurface, NULL);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX7(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX8_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirectDrawSurface7 *pTex;
+ IDirectDrawSurface7 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ DDSURFACEDESC2 ddsd;
+ int i;
+ DDSCAPS2 ddsCaps;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+
+ __try {
+
+ ddsd.dwSize = sizeof(ddsd);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ if ((level > 0) && (level >= ddsd.dwMipMapCount))
+ return; // Level does not exist
+
+ ZeroMemory(&ddsCaps, sizeof(ddsCaps));
+ pSurface = pTex;
+ for (i=0; i<level; i++) {
+ ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+ hr = IDirectDrawSurface7_GetAttachedSurface(
+ pSurface,
+ &ddsCaps,
+ &pSurface);
+ if(SUCCEEDED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ } else {
+ return;
+ }
+ }
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirectDrawSurface7_Lock(pSurface, &rcDstRect, &ddsd, 0, 0);
+ if (FAILED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)),
+ ddsd.lpSurface,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ ddsd.lPitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirectDrawSurface7_Unlock(pSurface, &rcDstRect);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX7( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX7(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX7(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ __try {
+
+ if (tObj) {
+ IDirectDrawSurface7 *pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX7_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx7 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx7 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DTEXTUREMINFILTER minfilter;
+ D3DTEXTUREMIPFILTER mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirectDrawSurface7 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ }
+
+ __try {
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX7_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX7_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX7_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ // Unsupported by DX7
+// dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+// _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+// gldLogMessage(GLDLOG_WARN, "GL_BLEND\n");
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX7(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwPasses;
+ _GLD_DX7_DEV(ValidateDevice(gld->pDev, &dwPasses));
+#if 0
+ if (FAILED(hr)) {
+ gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+ }
+#endif
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c
new file mode 100644
index 00000000000..a85620dde8d
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c
@@ -0,0 +1,257 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+/*
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4));
+}
+*/
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ tnl_render_func *tab;
+ GLint pass;
+ GLD_pb_dx7 *gldPB = &gld->PB3d;
+ DWORD dwFlags;
+
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_TRUE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX7;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX7;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX7;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX7;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX7;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX7;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX7;
+ }
+
+// _GLD_DX7_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY;
+ _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length)
+ {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX7_VB(Unlock(gldPB->pVB));
+
+// _GLD_DX7_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_PROJECTION, &gld->matProjection));
+ _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines, 0));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles, 0));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+//---------------------------------------------------------------------------
+
+const struct tnl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c
new file mode 100644
index 00000000000..0a57bde2588
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c
@@ -0,0 +1,423 @@
+/* $Id: gld_vb_mesa_render_dx7.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 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.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+tnl_points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX7,
+ gld_Points2D_DX7,
+ gld_Points2D_DX7,
+ gld_Points2D_DX7
+};
+tnl_line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX7,
+ gld_Line2DSmooth_DX7,
+ gld_Line2DFlat_DX7,
+ gld_Line2DSmooth_DX7,
+};
+tnl_triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX7,
+ gld_Triangle2DSmooth_DX7,
+ gld_Triangle2DFlatExtras_DX7,
+ gld_Triangle2DSmoothExtras_DX7
+};
+tnl_quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX7,
+ gld_Quad2DSmooth_DX7,
+ gld_Quad2DFlatExtras_DX7,
+ gld_Quad2DSmoothExtras_DX7
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx7 *gldPB;
+ DWORD dwFlags;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ gldPB = &gld->PB2d;
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+
+ dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY;
+ _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+
+ // Allocate primitive pointers - gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length) {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX7_VB(Unlock(gldPB->pVB));
+
+ if (gldPB->nPoints) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines*2, 0));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles*3, 0));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+const struct tnl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
new file mode 100644
index 00000000000..0f8fe33eb15
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
@@ -0,0 +1,1611 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+//#include "gld_dxerr8.h"
+#include "gld_dx7.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+// Uncomment this for persistant resources
+//#define _GLD_PERSISTANT
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DX_SF_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+*/
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+// HINSTANCE hD3D8DLL; // Handle to d3d8.dll
+// FNDIRECT3DCREATE7 fnDirect3DCreate7; // Direct3DCreate8 function prototype
+// BOOL bDirect3D; // Persistant Direct3D7 exists
+// BOOL bDirect3DDevice; // Persistant Direct3DDevice7 exists
+// IDirect3D7 *pD3D; // Persistant Direct3D7
+// IDirect3DDevice7 *pDev; // Persistant Direct3DDevice7
+ BOOL bD3DXStarted;
+} GLD_dx7_globals;
+
+// These are "global" to all DX7 contexts. KeithH
+static GLD_dx7_globals dx7Globals;
+
+// Added for correct clipping of multiple open windows. (DaveM)
+LPDIRECTDRAWSURFACE7 lpDDSPrimary = NULL;
+LPDIRECTDRAWCLIPPER lpDDClipper = NULL;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ D3DXGetErrorString(hr, nBufSize, buf);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+//
+// DX7 does not support multisample
+/*
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D8 *pD3D8,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+*/
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx7 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx7 *lpCtx,
+ GLD_pb_dx7 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+ D3DVERTEXBUFFERDESC vbdesc;
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = MAX_ARRAY_LOCK_SIZE;
+
+ // Max vertex buffer size limited in DX7. (DaveM)
+ if (dwMaxVertices*9 > D3DMAXNUMVERTICES)
+ dwMaxVertices = D3DMAXNUMVERTICES/9;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ vbdesc.dwSize = sizeof(vbdesc);
+ vbdesc.dwCaps = gldVB->dwCreateFlags;
+ vbdesc.dwFVF = gldVB->dwFVF;
+ vbdesc.dwNumVertices = dwMaxVertices * 9;
+
+/* hResult = IDirect3DDevice8_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+RAgldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB);*/
+ hResult = IDirect3D7_CreateVertexBuffer(
+ lpCtx->pD3D,
+ &vbdesc,
+ &gldVB->pVB,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX8 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D8
+ // bPersistantBuffers: applies to IDirect3DDevice8
+ //
+
+// D3DDEVTYPE d3dDevType;
+// D3DPRESENT_PARAMETERS d3dpp;
+// D3DDISPLAYMODE d3ddm;
+// DWORD dwBehaviourFlags;
+// D3DADAPTER_IDENTIFIER8 d3dIdent;
+
+ HRESULT hr;
+ GLD_driver_dx7 *lpCtx = NULL;
+ D3DX_VIDMODEDESC d3ddm;
+
+ // Parameters for D3DXCreateContextEx
+ // These will be different for fullscreen and windowed
+ DWORD dwDeviceIndex;
+ DWORD dwFlags;
+ HWND hwnd;
+ HWND hwndFocus;
+ DWORD numColorBits;
+ DWORD numAlphaBits;
+ DWORD numDepthBits;
+ DWORD numStencilBits;
+ DWORD numBackBuffers;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DWORD refreshRate;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces (in reverse order)
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext = NULL;
+ } else {
+ lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+// d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level
+ // of HW acceleration.
+ dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT;
+
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+#ifdef _GLD_PERSISTANT
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx7Globals.bDirect3D) {
+ lpCtx->pD3D = dx7Globals.pD3D;
+ IDirect3D7_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+#endif
+/*
+ // Create Direct3D7 object
+ lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+#ifdef _GLD_PERSISTANT
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx8Globals.bDirect3D) {
+ dx7Globals.pD3D = lpCtx->pD3D;
+ IDirect3D7_AddRef(dx7Globals.pD3D);
+ dx7Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+#endif
+/*
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+#if 0
+ // Get device caps
+ hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+#endif
+
+ //
+ // Create the Direct3D context
+ //
+
+#ifdef _GLD_PERSISTANT
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D8 as well
+ // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D && dx7Globals.pDev) {
+ lpCtx->pDev = dx7Globals.pDev;
+ IDirect3DDevice7_AddRef(dx7Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+#endif
+/*
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // FullScreen_PresentationInterval must be default for Windowed mode
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ hResult = IDirect3D8_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+ // Create D3DX context
+ if (ctx->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+
+ // Fullscreen Parameters
+ dwFlags = D3DX_CONTEXT_FULLSCREEN;
+ hwnd = ctx->hWnd;
+ hwndFocus = ctx->hWnd;
+ numColorBits = ctx->lpPF->pfd.cColorBits;
+ numAlphaBits = ctx->lpPF->pfd.cAlphaBits;
+ numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits;
+ numStencilBits = ctx->lpPF->pfd.cStencilBits;
+ numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer
+ dwWidth = d3ddm.width;
+ dwHeight = d3ddm.height;
+ refreshRate = d3ddm.refreshRate; // D3DX_DEFAULT;
+ } else {
+ //
+ // WINDOWED
+ //
+
+ // Windowed Parameters
+ dwFlags = 0; // No flags means "windowed"
+ hwnd = ctx->hWnd;
+ hwndFocus = (HWND)D3DX_DEFAULT;
+ numColorBits = D3DX_DEFAULT; // Use Desktop depth
+ numAlphaBits = ctx->lpPF->pfd.cAlphaBits;
+ numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits;
+ numStencilBits = ctx->lpPF->pfd.cStencilBits;
+ numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer
+ dwWidth = ctx->dwWidth;
+ dwHeight = ctx->dwHeight;
+ refreshRate = D3DX_DEFAULT;
+ }
+ hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus,
+ numColorBits, numAlphaBits, numDepthBits, numStencilBits,
+ numBackBuffers,
+ dwWidth, dwHeight, refreshRate,
+ &lpCtx->pD3DXContext);
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Obtain D3D7 interfaces from ID3DXContext
+// lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext);
+ lpCtx->pDD = lpCtx->pD3DXContext->lpVtbl->GetDD(lpCtx->pD3DXContext);
+ if (lpCtx->pDD == NULL)
+ goto return_with_error;
+ lpCtx->pD3D = lpCtx->pD3DXContext->lpVtbl->GetD3D(lpCtx->pD3DXContext);
+ if (lpCtx->pD3D == NULL)
+ goto return_with_error;
+ lpCtx->pDev = lpCtx->pD3DXContext->lpVtbl->GetD3DDevice(lpCtx->pD3DXContext);
+ if (lpCtx->pDev == NULL)
+ goto return_with_error;
+
+ // Need to manage clipper manually for multiple windows
+ // since DX7 D3DX utility lib does not appear to do that. (DaveM)
+ if (!ctx->bFullscreen) {
+ // Get primary surface too
+ lpDDSPrimary = lpCtx->pD3DXContext->lpVtbl->GetPrimary(lpCtx->pD3DXContext);
+ if (lpDDSPrimary == NULL) {
+ ddlogPrintf(DDLOG_WARN, "GetPrimary");
+ goto return_with_error;
+ }
+ // Create clipper for correct window updates
+ if (IDirectDraw7_CreateClipper(lpCtx->pDD, 0, &lpDDClipper, NULL) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "CreateClipper");
+ goto return_with_error;
+ }
+ // Set the window that the clipper belongs to
+ if (IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hwnd) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "SetHWnd");
+ goto return_with_error;
+ }
+ // Attach the clipper to the primary surface
+ if (IDirectDrawSurface7_SetClipper(lpDDSPrimary, lpDDClipper) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "SetClipper");
+ goto return_with_error;
+ }
+ }
+
+ // Get device caps
+ IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps);
+
+ // Determine HW TnL
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+#ifdef _GLD_PERSISTANT
+ if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) {
+ dx7Globals.pDev = lpCtx->pDev;
+ dx7Globals.bDirect3DDevice = TRUE;
+ }
+#endif
+
+#if 0
+ // Dump some useful stats
+ hResult = IDirect3D8_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+#endif
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+// lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwCreateFlags = D3DVBCAPS_DONOTCLIP |
+ D3DVBCAPS_SYSTEMMEMORY |
+ D3DVBCAPS_WRITEONLY;
+ hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hr))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+// lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwCreateFlags = D3DVBCAPS_WRITEONLY;
+
+ hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hr))
+ goto return_with_error;
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ //SAFE_RELEASE(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx7 *gld = NULL;
+// D3DDEVTYPE d3dDevType;
+// D3DPRESENT_PARAMETERS d3dpp;
+// D3DDISPLAYMODE d3ddm;
+ D3DX_VIDMODEDESC d3ddm;
+ HRESULT hr;
+ DWORD dwWidth, dwHeight;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice7_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+/*
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+*/
+ // Release objects before Reset()
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+
+/*
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+*/
+ // Obtain dimensions of 'window'
+ if (ctx->bFullscreen) {
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ dwWidth = d3ddm.width;
+ dwHeight = d3ddm.height;
+ } else {
+ dwWidth = ctx->dwWidth;
+ dwHeight = ctx->dwHeight;
+ }
+
+ // Resize context
+ hr = gld->pD3DXContext->lpVtbl->Resize(gld->pD3DXContext, dwWidth, dwHeight);
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "gldResizeDrawable_DX: Resize failed", hr);
+ return FALSE;
+ }
+
+ // Clear the resized surface (DaveM)
+ {
+ D3DVIEWPORT7 vp1, vp2;
+ IDirect3DDevice7_GetViewport(gld->pDev, &vp1);
+ IDirect3DDevice7_GetViewport(gld->pDev, &vp2);
+ vp2.dwX = 0;
+ vp2.dwY = 0;
+ vp2.dwWidth = dwWidth;
+ vp2.dwHeight = dwHeight;
+ IDirect3DDevice7_SetViewport(gld->pDev, &vp2);
+ hr = gld->pD3DXContext->lpVtbl->Clear(gld->pD3DXContext, D3DCLEAR_TARGET);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldResizeDrawable_DX: Clear failed", hr);
+ IDirect3DDevice7_SetViewport(gld->pDev, &vp1);
+ }
+
+ //
+ // Recreate objects
+ //
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx7 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+ // Destroy Primtive Buffers
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ // Release DX interfaces (in reverse order)
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ //SAFE_RELEASE(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+/*
+ ZeroMemory(&dx7Globals, sizeof(dx7Globals));
+
+ // Load d3d8.dll
+ dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
+ if (dx8Globals.hD3D8DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate8
+ dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
+ if (dx8Globals.fnDirect3DCreate8 == NULL) {
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ return FALSE;
+ }
+*/
+
+ // Initialise D3DX
+ return FAILED(D3DXInitialize()) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+/*
+ if (dx7Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx7Globals.pDev);
+ dx7Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx7Globals.bDirect3D) {
+ SAFE_RELEASE(dx7Globals.pD3D);
+ dx7Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ dx8Globals.hD3D8DLL = NULL;
+ dx8Globals.fnDirect3DCreate8 = NULL;
+*/
+ return FAILED(D3DXUninitialize()) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DX_SURFACEFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+/* case D3DX_SF_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;*/
+ case D3DX_SF_R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DX_SURFACEFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DX_SF_Z16S0:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DX_SF_Z32S0:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DX_SF_Z15S1:
+ *cDepthBits = 15;
+ *cStencilBits = 1;
+ return;
+ case D3DX_SF_Z24S8:
+ *cDepthBits = 24;
+ *cStencilBits = 8;
+ return;
+ case D3DX_SF_S1Z15:
+ *cDepthBits = 15;
+ *cStencilBits = 1;
+ return;
+ case D3DX_SF_S8Z24:
+ *cDepthBits = 24;
+ *cStencilBits = 8;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+/*
+BOOL GLD_CheckDepthStencilMatch(
+ DWORD dwDeviceIndex,
+ D3DX_SURFACEFORMAT sfWant)
+{
+ // Emulate function built in to DX9
+ D3DX_SURFACEFORMAT sfFound;
+ int i;
+ int nFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER);
+ if (nFormats) {
+ for (i=0; i<nFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER, i, &sfFound); }
+ if (sfFound == sfWant)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+*/
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldFindCompatibleDepthStencilFormat(
+ DWORD dwDeviceIndex)
+{
+ // Jump through some hoops...
+
+ ID3DXContext *pD3DXContext = NULL;
+ IDirectDrawSurface7 *pZBuffer = NULL;
+ DDPIXELFORMAT ddpf;
+ HWND hWnd;
+
+ // Get an HWND - use Desktop's
+ hWnd = GetDesktopWindow();
+
+ // Create a fully specified default context.
+ D3DXCreateContextEx(dwDeviceIndex, 0, hWnd, (HWND)D3DX_DEFAULT,
+ D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
+ D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
+ &pD3DXContext);
+
+ // Obtain depth buffer that was created in context
+ pZBuffer = pD3DXContext->lpVtbl->GetZBuffer(pD3DXContext);
+
+ // Get pixel format of depth buffer
+ ddpf.dwSize = sizeof(ddpf);
+ pZBuffer->lpVtbl->GetPixelFormat(pZBuffer, &ddpf);
+ // Done with surface - release it
+ pZBuffer->lpVtbl->Release(pZBuffer);
+
+ // Done with D3DX context
+ pD3DXContext->lpVtbl->Release(pD3DXContext);
+
+ // Convert and return
+ return D3DXMakeSurfaceFormat(&ddpf);
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DX_DEVICEDESC d3dxdd;
+ D3DX_VIDMODEDESC d3ddm;
+ D3DX_SURFACEFORMAT fmt[64]; // 64 should be enough...
+ DWORD dwDeviceIndex;
+ DWORD surfClassFlags;
+// IDirect3D7 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0; // Total formats
+ int nDepthOnlyFormats = 0;
+ int nDepthStencilFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+/* const D3DFORMAT DepthStencil[4] = {
+ D3DX_SF_Z16S0, //D3DX_SF_D16,
+ D3DX_SF_Z15S1, //D3DX_SF_D15S1,
+ D3DX_SF_Z32S0, //D3DX_SF_D32,
+ D3DX_SF_Z24S8, //D3DX_SF_D24S8,
+ //D3DX_SF_D24X8,
+ //D3DX_SF_D24X4S4,
+ };*/
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 7.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT;
+
+ // Dump description
+ D3DXGetDeviceDescription(dwDeviceIndex, &d3dxdd);
+ ddlogPrintf(GLDLOG_SYSTEM, "Device: %s", d3dxdd.driverDesc);
+
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+
+#if 0
+ // Phooey - this don't work...
+/*
+ // Since D3DXGetMaxSurfaceFormats() can lie to us, we'll need a workaround.
+ // Explicitly test for matching depth/stencil to display bpp.
+ if (d3ddm.bpp <= 16) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z15S1))
+ fmt[nSupportedFormats++] = D3DX_SF_Z15S1;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S1Z15))
+ fmt[nSupportedFormats++] = D3DX_SF_S1Z15;
+ // Didn't find anything? Try default
+ if (nSupportedFormats == 0) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
+ }
+ } else {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z24S8))
+ fmt[nSupportedFormats++] = D3DX_SF_Z24S8;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S8Z24))
+ fmt[nSupportedFormats++] = D3DX_SF_S8Z24;
+ // Didn't find anything? Try default
+ if (nSupportedFormats == 0) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
+ }
+ }
+*/
+ // Go the Whole Hog...
+ fmt[nSupportedFormats++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex);
+#else
+ //
+ // Depth buffer formats WITHOUT stencil
+ //
+ surfClassFlags = D3DX_SC_DEPTHBUFFER;
+ nDepthOnlyFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
+ //
+ // Depth buffer formats WITH stencil
+ //
+ surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
+ nDepthStencilFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
+
+ // Work out how many formats we have in total
+ if ((nDepthOnlyFormats + nDepthStencilFormats) == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Get depth buffer formats WITHOUT stencil
+ surfClassFlags = D3DX_SC_DEPTHBUFFER;
+ for (i=0; i<nDepthOnlyFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]);
+ }
+ // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER
+ /*
+ // Get depth buffer formats WITH stencil
+ surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
+ for (i=0; i<nDepthStencilFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]);
+ }
+ */
+#endif
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = (nSupportedFormats)*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+// _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ cColorBits = d3ddm.bpp;
+ cAlphaBits = 0;
+ switch (d3ddm.bpp) {
+ case 15:
+ cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
+ break;
+ case 16:
+ cRedBits = 5; cGreenBits = 6; cBlueBits = 5;
+ break;
+ case 24:
+ case 32:
+ cRedBits = 8; cGreenBits = 8; cBlueBits = 8;
+ break;
+ default:
+ cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
+ }
+
+ //
+ // Add single-buffer formats
+ //
+
+/* // Single-buffer, no depth-stencil buffer
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DX_SF_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DX_SF_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx7 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps.wMaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX7)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX7;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+// MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
+ MaxTextureSize = min(gld->d3dCaps.dwMaxTextureHeight, gld->d3dCaps.dwMaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // TODO: Check this again for Mesa 5
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ // Defaults
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_LIGHTING, FALSE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_DITHERENABLE, TRUE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
+
+ // Set texture coord set to be used with each stage
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_TEXCOORDINDEX, 0);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_TEXCOORDINDEX, 1);
+
+ // Set up Depth buffer
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DX_SF_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice7_SetTransform(gld->pDev, D3DTRANSFORMSTATE_VIEW, &vm);
+ }
+
+// DX7 does not support D3DRS_SOFTWAREVERTEXPROCESSING
+/*
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+*/
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+// gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+ gld->bHasHWTnL ? "Enabled" : "Unavailable");
+//#endif
+
+ // Set up interfaces to Mesa
+ gldEnableExtensions_DX7(lpCtx->glCtx);
+ gldInstallPipeline_DX7(lpCtx->glCtx);
+ gldSetupDriverPointers_DX7(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx7 *gld = NULL;
+ DWORD dwFlags;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+
+ // End the scene if one is started
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice7_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Needed by D3DX for MDI multi-window apps (DaveM)
+ if (lpDDClipper)
+ IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hWnd);
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+// hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+ // Set refresh sync flag
+ dwFlags = glb.bWaitForRetrace ? 0 : D3DX_UPDATE_NOVSYNC;
+ // Render and show frame
+ hr = gld->pD3DXContext->lpVtbl->UpdateFrame(gld->pD3DXContext, dwFlags);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: UpdateFrame", hr);
+
+ if (hr == DDERR_SURFACELOST) {
+ hr = gld->pD3DXContext->lpVtbl->RestoreSurfaces(gld->pD3DXContext);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: RestoreSurfaces", hr);
+ }
+
+exit_swap:
+ // Begin a new scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+// D3DDISPLAYMODE d3ddm;
+ D3DX_VIDMODEDESC d3ddm;
+ HRESULT hr;
+ GLD_driver_dx7 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+// hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ hr = D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+// _BitsFromDisplayFormat(d3ddm.Format,
+// &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.width;
+ glddm->Height = d3ddm.height;
+ glddm->BPP = d3ddm.bpp;
+ glddm->Refresh = d3ddm.refreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
new file mode 100644
index 00000000000..0a6d9f8555c
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
@@ -0,0 +1,1176 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX8(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX8(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX8(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX8(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX8(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+// ctx->Color.ClearColor[1],
+// ctx->Color.ClearColor[2],
+// ctx->Color.ClearColor[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D8 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX8_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX8(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX8(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX8(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest));
+
+ // Color mask
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ int iOffset = 0;
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ iOffset = (int)ctx->Polygon.OffsetUnits;
+ if (iOffset < 0)
+ iOffset = -iOffset;
+ else
+ iOffset = 0; // D3D can't push away
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZBIAS, iOffset));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX8(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX8(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DVIEWPORT8 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX8_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX8(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx8 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE));
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX8(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX8(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX8(_NEW_TEXTURE); // extern, so guard with _DX8
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX8(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DVIEWPORT8 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX8(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX8(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX8;
+ ctx->Driver.Clear = gld_Clear_DX8;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX8;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX8;
+ ctx->Driver.Finish = gld_Finish_DX8;
+ ctx->Driver.Flush = gld_Flush_DX8;
+ ctx->Driver.Error = gld_Error_DX8;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX8;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX8;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX8;
+ ctx->Driver.Bitmap = gld_Bitmap_DX8;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX8;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX8;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX8;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX8;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX8;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX8;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX8; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX8;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX8;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX8;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX8;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX8;
+// ctx->Exec->Ortho = gldOrthoHook_DX8;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h
new file mode 100644
index 00000000000..7efec7cae80
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.0 header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX8_H
+#define _GLD_DX8_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+//#ifndef STRICT
+//#define STRICT
+//#endif
+
+//#define WIN32_LEAN_AND_MEAN
+//#include <windows.h>
+#include <d3d8.h>
+#include <d3dx8.h>
+
+// MS screwed up with the DX8.1 SDK - there's no compile-time
+// method of compiling for 8.0 via the 8.1 SDK unless you
+// "make sure you don't use any 8.1 interfaces".
+// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces.
+//
+// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95).
+// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95).
+//
+#define D3D_SDK_VERSION_DX8_SUPPORT_WIN95 120
+
+// Typedef for obtaining function from d3d8.dll
+typedef IDirect3D8* (WINAPI *FNDIRECT3DCREATE8) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX8(func) _GLD_TEST_HRESULT(IDirect3D8_##func##)
+#define _GLD_DX8_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice8_##func##)
+#define _GLD_DX8_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer8_##func##)
+#define _GLD_DX8_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture8_##func##)
+#else
+#define _GLD_DX8(func) IDirect3D8_##func
+#define _GLD_DX8_DEV(func) IDirect3DDevice8_##func
+#define _GLD_DX8_VB(func) IDirect3DVertexBuffer8_##func
+#define _GLD_DX8_TEX(func) IDirect3DTexture8_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB8(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer8_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE8(p) \
+{ \
+ if (p) { \
+ IDirect3DSurface8_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+/*
+// Internal pipeline
+typedef enum {
+ GLD_PIPELINE_MESA = 0, // Mesa pipeline
+ GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline
+ GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader
+} GLD_tnl_pipeline;
+*/
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX8 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// DX8 Vertex Shader
+typedef struct {
+ DWORD hShader; // If NULL, shader is invalid and cannot be used
+ BOOL bHardware; // If TRUE then shader was created for hardware,
+ // otherwise shader was created for software.
+} GLD_vertexShader;
+*/
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3DDevice8::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwUsage; // Usage flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+ DWORD dwPool; // Pool flags
+
+ IDirect3DVertexBuffer8 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx8;
+
+// GLDirect DX8 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DFORMAT RenderFormat; // Format of back/front buffer
+ D3DFORMAT DepthFormat; // Format of depth/stencil
+// float fFlipWindowY; // Value for flipping viewport Y coord
+
+ // Direct3D vars
+ D3DCAPS8 d3dCaps8;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ IDirect3D8 *pD3D; // Base Direct3D8 interface
+ IDirect3DDevice8 *pDev; // Direct3D8 Device interface
+ GLD_pb_dx8 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx8 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DXMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DXMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ // Direct3D vars for two-sided lighting
+// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting
+// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders
+
+
+// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline
+ GLD_pipeline_usage PipelineUsage;
+} GLD_driver_dx8;
+
+#define GLD_GET_DX8_DRIVER(c) (GLD_driver_dx8*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX8(LPCSTR a);
+void gldEnableExtensions_DX8(GLcontext *ctx);
+void gldInstallPipeline_DX8(GLcontext *ctx);
+void gldSetupDriverPointers_DX8(GLcontext *ctx);
+//void gldResizeBuffers_DX8(GLcontext *ctx);
+void gldResizeBuffers_DX8(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX8(GLcontext *ctx);
+void gld_DrawPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX8(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX8(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX8(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX8(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX8(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX8(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h
new file mode 100644
index 00000000000..f8e92b936e8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr8.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR8_H_
+#define _GLD_DXERR8_H_
+
+
+#include <d3d8.h>
+
+//
+// DXGetErrorString8
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString8A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString8 DXGetErrorString8W
+#else
+ #define DXGetErrorString8 DXGetErrorString8A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c
new file mode 100644
index 00000000000..108f12a9d16
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#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)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX8(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c
new file mode 100644
index 00000000000..2baea57443c
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct tnl_pipeline_stage _gld_d3d_render_stage;
+extern struct tnl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct tnl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX8(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
new file mode 100644
index 00000000000..700b5200862
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0f - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX8(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX8(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX8(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c
new file mode 100644
index 00000000000..f24b3cfb74d
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c
@@ -0,0 +1,2046 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include <d3dx8tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREFILTERTYPE _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREFILTERTYPE *min_filter,
+ D3DTEXTUREFILTERTYPE *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DFMT_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DFMT_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DFMT_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DFMT_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DFMT_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DFMT_X4R4G4B4;
+ case GL_RGB5:
+ return D3DFMT_X1R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DFMT_R8G8B8;
+ case GL_RGBA4:
+ return D3DFMT_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DFMT_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DFMT_A1R5G5B5;
+ }
+
+ // Return an acceptable default
+ return D3DFMT_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirect3DTexture8 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+ D3DSURFACE_DESC desc;
+ _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ switch (desc.Format) {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ return GL_RGB;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_A4L4:
+ return GL_RGBA;
+ case D3DFMT_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DFMT_DXT1:
+ return GL_RGBA;
+ case D3DFMT_DXT2:
+ return GL_RGB;
+ case D3DFMT_DXT3:
+ return GL_RGBA;
+ case D3DFMT_DXT4:
+ return GL_RGB;
+ case D3DFMT_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DFMT_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DFMT_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DFMT_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DFMT_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DFMT_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DFMT_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DFMT_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DFMT_A8:
+ return &_mesa_texformat_a8;
+ case D3DFMT_L8:
+ return &_mesa_texformat_l8;
+ case D3DFMT_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DFMT_X1R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DFMT_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ assert(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX8(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX8(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirect3DSurface8 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTexture;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pSurface;
+ _GLD_IMAGE_VERTEX v[4];
+ HRESULT hr;
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Create a texture to hold image
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ width, height,
+ 1, // miplevels
+ 0, // usage
+ D3DFMT_A8R8G8B8, // format
+ D3DPOOL_MANAGED, // pool
+ &pTexture);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTexture, 0, &pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture8_Release(pTexture);
+ return hr;
+ }
+
+ // Copy image into texture
+ hr = D3DXLoadSurfaceFromSurface(
+ pSurface, NULL, NULL, // Dest surface
+ pImage, NULL, NULL, // Src surface
+ D3DX_FILTER_NONE,
+ 0);
+ IDirect3DSurface8_Release(pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture8_Release(pTexture);
+ return hr;
+ }
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ IDirect3DTexture8_GetLevelDesc(pTexture, 0, &d3dsd);
+ ScaleWidth = (float)width / (float)d3dsd.Width;
+ ScaleHeight = (float)height / (float)d3dsd.Height;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice8_SetTexture(gld->pDev, 0, pTexture);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ IDirect3DDevice8_SetVertexShader(gld->pDev, _GLD_FVF_IMAGE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice8_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX));
+
+ // Release texture
+ IDirect3DDevice8_SetTexture(gld->pDev, 0, NULL);
+ IDirect3DTexture8_Release(pTexture);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX8(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+
+ const struct gl_texture_format *MesaFormat;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pImage);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+
+ // unpack image, apply transfer ops and store directly in texture
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirect3DSurface8_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX8(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pBackbuffer = NULL;
+ IDirect3DSurface8 *pNativeImage = NULL;
+ IDirect3DSurface8 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pNativeImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pCanonicalImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface8_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX8_return:
+ SAFE_RELEASE_SURFACE8(pCanonicalImage);
+ SAFE_RELEASE_SURFACE8(pNativeImage);
+ SAFE_RELEASE_SURFACE8(pBackbuffer);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX8(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pImage);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);
+ IDirect3DSurface8_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX8(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ BYTE *pTempBitmap;
+ D3DCOLOR clBitmapOne, clBitmapZero;
+ D3DCOLOR *pBits;
+ const GLubyte *src;
+ int i, j, k;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pImage);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ pBits = (D3DCOLOR*)d3dLockedRect.pBits;
+
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch));
+ src = (const GLubyte *) _mesa_image_address(2,
+ &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ FREE(pTempBitmap);
+
+/*
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ GL_BITMAP,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack);
+*/
+ IDirect3DSurface8_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ D3DFORMAT d3dFormat;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ D3DSURFACE_DESC d3dsd;
+ _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &d3dsd));
+ // Release existing texture if not compatible
+ if ((d3dsd.Width == texImage->Width) ||
+ (d3dsd.Height == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX8_TEX(Release(pTex));
+ }
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ D3DXCreateTexture(
+ gld->pDev,
+ texImage->Width,
+ texImage->Height,
+ // TODO: Re-evaluate mipmapping
+ (glb.bUseMipmaps) ? D3DX_DEFAULT : 1,
+ 0, // Usage
+ d3dFormat,
+ D3DPOOL_MANAGED,
+ &pTex);
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX8(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface8_GetDesc(pSurface, &d3dsd);
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirect3DSurface8_UnlockRect(pSurface);
+ IDirect3DSurface8_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX8(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX8_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface8_GetDesc(pSurface, &d3dsd);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirect3DSurface8_UnlockRect(pSurface);
+ IDirect3DSurface8_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX8( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX8(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX8(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ if (tObj) {
+ IDirect3DTexture8 *pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX8_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx8 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx8 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DTEXTUREFILTERTYPE minfilter;
+ D3DTEXTUREFILTERTYPE mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirect3DTexture8 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ }
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX8_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX8_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX8_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX8(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE;
+ //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE;
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+// GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ DWORD dwPasses;
+ _GLD_DX8_DEV(ValidateDevice(gld->pDev, &dwPasses));
+// if (FAILED(hr)) {
+// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+// }
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c
new file mode 100644
index 00000000000..cafbf4f5c50
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c
@@ -0,0 +1,249 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4));
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ tnl_render_func *tab;
+ GLint pass;
+ GLD_pb_dx8 *gldPB = &gld->PB3d;
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_TRUE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX8;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX8;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX8;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX8;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX8;
+ }
+
+ _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length)
+ {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX8_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection));
+ _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+const struct tnl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c
new file mode 100644
index 00000000000..81414a31dde
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c
@@ -0,0 +1,449 @@
+/* $Id: gld_vb_mesa_render_dx8.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 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.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+tnl_points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX8,
+ gld_Points2D_DX8,
+ gld_Points2D_DX8,
+ gld_Points2D_DX8
+};
+tnl_line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX8,
+ gld_Line2DSmooth_DX8,
+ gld_Line2DFlat_DX8,
+ gld_Line2DSmooth_DX8,
+};
+tnl_triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX8,
+ gld_Triangle2DSmooth_DX8,
+ gld_Triangle2DFlatExtras_DX8,
+ gld_Triangle2DSmoothExtras_DX8
+};
+tnl_quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX8,
+ gld_Quad2DSmooth_DX8,
+ gld_Quad2DFlatExtras_DX8,
+ gld_Quad2DSmoothExtras_DX8
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx8 *gldPB;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets
+ // stream, indices and shader to default values of NULL or 0.
+/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) &&
+ gld->VStwosidelight.hShader &&
+ !ctx->Fog.Enabled)
+ {
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware);
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+ gldPB = &gld->PBtwosidelight;
+ tnl->Driver.Render.Points = gld_Points2DTwoside_DX8;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX8;
+ tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX8;
+ } else {
+ tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX8;
+ tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX8;
+ }
+ } else {*/
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
+ gldPB = &gld->PB2d;
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+// }
+
+ _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length) {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX8_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ if (gldPB->nPoints) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+
+//---------------------------------------------------------------------------
+
+const struct tnl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
new file mode 100644
index 00000000000..690f68b68f1
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
@@ -0,0 +1,1335 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+#include "gld_dxerr8.h"
+#include "gld_dx8.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DFMT_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+ HINSTANCE hD3D8DLL; // Handle to d3d8.dll
+ FNDIRECT3DCREATE8 fnDirect3DCreate8; // Direct3DCreate8 function prototype
+ BOOL bDirect3D; // Persistant Direct3D8 exists
+ BOOL bDirect3DDevice; // Persistant Direct3DDevice8 exists
+ IDirect3D8 *pD3D; // Persistant Direct3D8
+ IDirect3DDevice8 *pDev; // Persistant Direct3DDevice8
+} GLD_dx8_globals;
+
+// These are "global" to all DX8 contexts. KeithH
+static GLD_dx8_globals dx8Globals;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ D3DXGetErrorString(hr, buf, nBufSize);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D8 *pD3D8,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx8 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx8 *lpCtx,
+ GLD_pb_dx8 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = MAX_ARRAY_LOCK_SIZE;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ hResult = IDirect3DDevice8_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+ gldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX8 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+LPVOID lpOpaque1 = NULL;
+LPVOID lpOpaque2 = NULL;
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D8
+ // bPersistantBuffers: applies to IDirect3DDevice8
+ //
+
+ HRESULT hResult;
+ GLD_driver_dx8 *lpCtx = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ DWORD dwBehaviourFlags;
+ D3DADAPTER_IDENTIFIER8 d3dIdent;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ } else {
+ lpCtx = (GLD_driver_dx8*)malloc(sizeof(GLD_driver_dx8));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx8Globals.bDirect3D) {
+ lpCtx->pD3D = dx8Globals.pD3D;
+ IDirect3D8_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create Direct3D8 object
+ lpCtx->pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx8Globals.bDirect3D) {
+ dx8Globals.pD3D = lpCtx->pD3D;
+ IDirect3D8_AddRef(dx8Globals.pD3D);
+ dx8Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Get device caps
+ hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ //
+ // Create the Direct3D context
+ //
+
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D8 as well
+ // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D && dx8Globals.pDev) {
+ lpCtx->pDev = dx8Globals.pDev;
+ IDirect3DDevice8_AddRef(dx8Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // FullScreen_PresentationInterval must be default for Windowed mode
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ // Add flag to tell D3D to be FPU-safe
+ if (!glb.bFastFPU)
+ dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
+ hResult = IDirect3D8_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D) {
+ dx8Globals.pDev = lpCtx->pDev;
+ dx8Globals.bDirect3DDevice = TRUE;
+ }
+
+/*
+ // See if DDraw interfaces are available (DaveM)
+ hResult = IDirect3D8_QueryInterface(lpCtx->pDev,
+ &IID_IDirectDraw7, (LPVOID*)&lpOpaque1);
+ if (FAILED(hResult) || lpOpaque1 == NULL) {
+ ddlogMessage(DDLOG_INFO, "DirectDraw QueryInterface unavailable\n");
+ }
+
+ hResult = IDirect3DDevice8_QueryInterface(lpCtx->pDev,
+ &IID_IDirectDrawSurface7, (LPVOID*)&lpOpaque2);
+ if (FAILED(hResult) || lpOpaque2 == NULL) {
+ ddlogMessage(DDLOG_INFO, "DirectDrawSurface QueryInterface unavialable\n");
+ }
+*/
+ // Dump some useful stats
+ hResult = IDirect3D8_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity(&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+ lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+ lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
+ lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
+ lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
+ lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
+ if (FAILED(hResult))
+ goto return_with_error;*/
+
+ // Now try and create the DX8 Vertex Shaders
+// _gldCreateVertexShaders(lpCtx);
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx8 *gld = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hResult;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice8_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+
+ // Destroy DX8 Vertex Shaders before Reset()
+// _gldDestroyVertexShaders(gld);
+
+ // Release POOL_DEFAULT objects before Reset()
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
+// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+
+ // Explicitly Clear resized surfaces (DaveM)
+ {
+ D3DVIEWPORT8 d3dvp1, d3dvp2;
+ IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp1);
+ IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp2);
+ d3dvp1.X = 0;
+ d3dvp1.Y = 0;
+ d3dvp1.Width = ctx->dwWidth;
+ d3dvp1.Height = ctx->dwHeight;
+ IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp1);
+ IDirect3DDevice8_Clear(gld->pDev,0,NULL,D3DCLEAR_TARGET,0,0,0);
+ IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp2);
+ }
+
+ //
+ // Recreate POOL_DEFAULT objects
+ //
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ }
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+ }
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
+// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+// }
+
+ // Recreate DX8 Vertex Shaders
+// _gldCreateVertexShaders(gld);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx8 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+ ZeroMemory(&dx8Globals, sizeof(dx8Globals));
+
+ // Load d3d8.dll
+ dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
+ if (dx8Globals.hD3D8DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate8
+ dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
+ if (dx8Globals.fnDirect3DCreate8 == NULL) {
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+ if (dx8Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx8Globals.pDev);
+ dx8Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx8Globals.bDirect3D) {
+ SAFE_RELEASE(dx8Globals.pD3D);
+ dx8Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ dx8Globals.hD3D8DLL = NULL;
+ dx8Globals.fnDirect3DCreate8 = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+ case D3DFMT_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DFMT_D32:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D15S1:
+ *cDepthBits = 16;
+ *cStencilBits = 1;
+ return;
+ case D3DFMT_D24S8:
+ *cDepthBits = 32;
+ *cStencilBits = 8;
+ return;
+ case D3DFMT_D16:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X8:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X4S4:
+ *cDepthBits = 32;
+ *cStencilBits = 4;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DDISPLAYMODE d3ddm;
+ D3DFORMAT fmt[6];
+ IDirect3D8 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+ const D3DFORMAT DepthStencil[6] = {
+ D3DFMT_D15S1,
+ D3DFMT_D16,
+ D3DFMT_D24X8,
+ D3DFMT_D24X4S4,
+ D3DFMT_D24S8,
+ D3DFMT_D32,
+ };
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 8.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ // Get a Direct3D 8.0 interface
+ pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (!pD3D) {
+ return FALSE;
+ }
+
+ // We will use the display mode format when finding compliant
+ // rendertarget/depth-stencil surfaces.
+ hr = IDirect3D8_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr)) {
+ IDirect3D8_Release(pD3D);
+ return FALSE;
+ }
+
+ // Run through the possible formats and detect supported formats
+ for (i=0; i<6; i++) {
+ hr = IDirect3D8_CheckDeviceFormat(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_SURFACE,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal.
+ continue;
+
+ // Verify that the depth format is compatible.
+ hr = IDirect3D8_CheckDepthStencilMatch(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ d3ddm.Format,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal, just means depth-stencil
+ // format is not compatible with this display mode.
+ continue;
+
+ fmt[nSupportedFormats++] = DepthStencil[i];
+ }
+
+ IDirect3D8_Release(pD3D);
+
+ if (nSupportedFormats == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = (nSupportedFormats)*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+ _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ //
+ // Add single-buffer formats
+ //
+
+ // Single-buffer, no depth-stencil buffer
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx8 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps8.MaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX8)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX8;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+ MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice8_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
+ }
+
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+ gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+//#endif
+
+ gldEnableExtensions_DX8(lpCtx->glCtx);
+ gldInstallPipeline_DX8(lpCtx->glCtx);
+ gldSetupDriverPointers_DX8(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx8 *gld = NULL;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice8_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+ hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hr;
+ GLD_driver_dx8 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+ hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+ _BitsFromDisplayFormat(d3ddm.Format,
+ &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.Width;
+ glddm->Height = d3ddm.Height;
+ glddm->BPP = cColorBits;
+ glddm->Refresh = d3ddm.RefreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
new file mode 100644
index 00000000000..1b01cb1f7f3
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
@@ -0,0 +1,1206 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX9(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX9(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX9(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX9(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX9(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D8 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+// gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height);
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX9_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX9(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX9(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX9(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest));
+
+ // Color mask
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ float fOffset = 0; // Changed from int to float for DX9
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ fOffset = ctx->Polygon.OffsetUnits;
+// if (iOffset < 0.0f)
+// iOffset = -iOffset;
+// else
+// iOffset = 0.0f; // D3D can't push away
+ }
+ // NOTE: SetRenderState() required a DWORD, so need to cast
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DEPTHBIAS, *((DWORD*)&fOffset)));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX9_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_SCISSOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Bail if IHV driver cannot scissor
+ if (!gld->bCanScissor)
+ return;
+
+ // Set scissor rect
+ if (ctx->Scissor.Enabled) {
+ RECT rcRect;
+ // Keep in mind that RECT's need an extra row and column
+ rcRect.left = ctx->Scissor.X;
+ rcRect.right = ctx->Scissor.X + ctx->Scissor.Width; // + 1;
+ rcRect.top = gldCtx->dwHeight - (ctx->Scissor.Y + ctx->Scissor.Height);
+ rcRect.bottom = rcRect.top + ctx->Scissor.Height;
+ IDirect3DDevice9_SetScissorRect(gld->pDev, &rcRect);
+ }
+
+ // Enable/disable scissor as required
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SCISSORTESTENABLE, ctx->Scissor.Enabled));
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx9 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX9(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx9 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, TRUE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX9(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX9(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX9(_NEW_TEXTURE); // extern, so guard with _DX9
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+ // Scissor Test: New for DX9
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+// _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX9(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX9(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX9(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX9;
+ ctx->Driver.Clear = gld_Clear_DX9;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX9;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX9;
+ ctx->Driver.Finish = gld_Finish_DX9;
+ ctx->Driver.Flush = gld_Flush_DX9;
+ ctx->Driver.Error = gld_Error_DX9;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX9;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX9;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX9;
+ ctx->Driver.Bitmap = gld_Bitmap_DX9;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX9;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX9;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX9;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX9;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX9;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX9;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX9;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX9;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX9;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX9;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX9;
+// ctx->Exec->Ortho = gldOrthoHook_DX9;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
new file mode 100644
index 00000000000..aec40ac9dd1
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
@@ -0,0 +1,327 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 9.0 header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX9_H
+#define _GLD_DX9_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+//#ifndef STRICT
+//#define STRICT
+//#endif
+
+//#define WIN32_LEAN_AND_MEAN
+//#include <windows.h>
+#include <d3d9.h>
+#include <d3dx9.h>
+
+// MS screwed up with the DX8.1 SDK - there's no compile-time
+// method of compiling for 8.0 via the 8.1 SDK unless you
+// "make sure you don't use any 8.1 interfaces".
+// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces.
+//
+// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95).
+// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95).
+//
+//#define D3D_SDK_VERSION_DX9_SUPPORT_WIN95 120
+//#define D3D_SDK_VERSION_DX91 220
+
+// Typedef for obtaining function from d3d8.dll
+typedef IDirect3D9* (WINAPI *FNDIRECT3DCREATE9) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX9(func) _GLD_TEST_HRESULT(IDirect3D9_##func##)
+#define _GLD_DX9_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice9_##func##)
+#define _GLD_DX9_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer9_##func##)
+#define _GLD_DX9_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture9_##func##)
+#else
+#define _GLD_DX9(func) IDirect3D9_##func
+#define _GLD_DX9_DEV(func) IDirect3DDevice9_##func
+#define _GLD_DX9_VB(func) IDirect3DVertexBuffer9_##func
+#define _GLD_DX9_TEX(func) IDirect3DTexture9_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB9(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE9(p) \
+{ \
+ if (p) { \
+ IDirect3DSurface9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+/*
+// Internal pipeline
+typedef enum {
+ GLD_PIPELINE_MESA = 0, // Mesa pipeline
+ GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline
+ GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader
+} GLD_tnl_pipeline;
+*/
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX9 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// DX8 Vertex Shader
+typedef struct {
+ DWORD hShader; // If NULL, shader is invalid and cannot be used
+ BOOL bHardware; // If TRUE then shader was created for hardware,
+ // otherwise shader was created for software.
+} GLD_vertexShader;
+*/
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3DDevice9::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwUsage; // Usage flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+ DWORD dwPool; // Pool flags
+
+ IDirect3DVertexBuffer9 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx9;
+
+// GLDirect DX9 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DFORMAT RenderFormat; // Format of back/front buffer
+ D3DFORMAT DepthFormat; // Format of depth/stencil
+// float fFlipWindowY; // Value for flipping viewport Y coord
+
+ // Direct3D vars
+ D3DCAPS9 d3dCaps9;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ IDirect3D9 *pD3D; // Base Direct3D9 interface
+ IDirect3DDevice9 *pDev; // Direct3D9 Device interface
+ GLD_pb_dx9 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx9 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DXMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DXMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ // Direct3D vars for two-sided lighting
+// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting
+// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders
+
+
+// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline
+ GLD_pipeline_usage PipelineUsage;
+
+ BOOL bCanScissor; // Scissor test - new for DX9
+} GLD_driver_dx9;
+
+#define GLD_GET_DX9_DRIVER(c) (GLD_driver_dx9*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX9(LPCSTR a);
+void gldEnableExtensions_DX9(GLcontext *ctx);
+void gldInstallPipeline_DX9(GLcontext *ctx);
+void gldSetupDriverPointers_DX9(GLcontext *ctx);
+//void gldResizeBuffers_DX9(GLcontext *ctx);
+void gldResizeBuffers_DX9(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX9(GLcontext *ctx);
+void gld_DrawPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX9(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX9(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX9(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX9(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX9(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
new file mode 100644
index 00000000000..1d6b7b1c760
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr9.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR9_H_
+#define _GLD_DXERR9_H_
+
+
+#include <d3d9.h>
+
+//
+// DXGetErrorString9
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString9A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString9W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString9 DXGetErrorString9W
+#else
+ #define DXGetErrorString9 DXGetErrorString9A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
new file mode 100644
index 00000000000..745c987602b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#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)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX9(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
new file mode 100644
index 00000000000..2b272aa6281
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct tnl_pipeline_stage _gld_d3d_render_stage;
+extern struct tnl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct tnl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX9(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
new file mode 100644
index 00000000000..65fd821276e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->data; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->data; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->data; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX9(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX9(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX9(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
new file mode 100644
index 00000000000..5a822356164
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
@@ -0,0 +1,2104 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include <d3dx9tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *)texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ texel[RCOMP] = CHAN_TO_FLOAT(src[0]);
+ texel[GCOMP] = CHAN_TO_FLOAT(src[1]);
+ texel[BCOMP] = CHAN_TO_FLOAT(src[2]);
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf8) * 255 / 0xf8 );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLchan *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_f_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLfloat *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLushort s = *src;
+ texel[RCOMP] = UBYTE_TO_FLOAT( ((s >> 8) & 0xf) * 255 / 0xf );
+ texel[GCOMP] = UBYTE_TO_FLOAT( ((s >> 4) & 0xf) * 255 / 0xf );
+ texel[BCOMP] = UBYTE_TO_FLOAT( ((s ) & 0xf) * 255 / 0xf );
+ texel[ACOMP] = 1.f;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ _mesa_texstore_argb8888, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X8R8G8B8, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X8R8G8B8, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X8R8G8B8, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb1555, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X1R5G5B5, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X1R5G5B5, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X1R5G5B5, /* FetchTexel3Df */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ _mesa_texstore_argb4444, /* StoreTexImageFunc */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+ gld_fetch_1d_texel_f_X4R4G4B4, /* FetchTexel1Df */
+ gld_fetch_2d_texel_f_X4R4G4B4, /* FetchTexel2Df */
+ gld_fetch_3d_texel_f_X4R4G4B4, /* FetchTexel3Df */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREFILTERTYPE _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREFILTERTYPE *min_filter,
+ D3DTEXTUREFILTERTYPE *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DFMT_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DFMT_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DFMT_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DFMT_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DFMT_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DFMT_X4R4G4B4;
+ case GL_RGB5:
+ return D3DFMT_X1R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DFMT_R8G8B8;
+ case GL_RGBA4:
+ return D3DFMT_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DFMT_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DFMT_A1R5G5B5;
+ }
+
+ // Return an acceptable default
+ return D3DFMT_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirect3DTexture9 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+ D3DSURFACE_DESC desc;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ switch (desc.Format) {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ return GL_RGB;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_A4L4:
+ return GL_RGBA;
+ case D3DFMT_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DFMT_DXT1:
+ return GL_RGBA;
+ case D3DFMT_DXT2:
+ return GL_RGB;
+ case D3DFMT_DXT3:
+ return GL_RGBA;
+ case D3DFMT_DXT4:
+ return GL_RGB;
+ case D3DFMT_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DFMT_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DFMT_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DFMT_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DFMT_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DFMT_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DFMT_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DFMT_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DFMT_A8:
+ return &_mesa_texformat_a8;
+ case D3DFMT_L8:
+ return &_mesa_texformat_l8;
+ case D3DFMT_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DFMT_X1R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DFMT_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ assert(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX9(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX9(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirect3DSurface9 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTexture;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pSurface;
+ _GLD_IMAGE_VERTEX v[4];
+ HRESULT hr;
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Create a texture to hold image
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ width, height,
+ 1, // miplevels
+ 0, // usage
+ D3DFMT_A8R8G8B8, // format
+ D3DPOOL_MANAGED, // pool
+ &pTexture);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ // Copy image into texture
+ hr = D3DXLoadSurfaceFromSurface(
+ pSurface, NULL, NULL, // Dest surface
+ pImage, NULL, NULL, // Src surface
+ D3DX_FILTER_NONE,
+ 0);
+ IDirect3DSurface9_Release(pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd);
+ ScaleWidth = (float)width / (float)d3dsd.Width;
+ ScaleHeight = (float)height / (float)d3dsd.Height;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE);
+
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+ IDirect3DDevice9_SetVertexShader(gld->pDev, NULL);
+ IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX));
+
+ // Release texture
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL);
+ IDirect3DTexture9_Release(pTexture);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX9(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+
+ const struct gl_texture_format *MesaFormat;
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+
+ // Mesa does not currently handle this format.
+ if (format == GL_BGR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX9(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer = NULL;
+ IDirect3DSurface9 *pNativeImage = NULL;
+ IDirect3DSurface9 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pNativeImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ // CopyRects has been removed for DX9.
+ //
+/* hr = IDirect3DDevice9_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pNativeImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pCanonicalImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(2,pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ MesaFormat->StoreImage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface9_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX9_return:
+ SAFE_RELEASE_SURFACE9(pCanonicalImage);
+ SAFE_RELEASE_SURFACE9(pNativeImage);
+ SAFE_RELEASE_SURFACE9(pBackbuffer);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX9(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+/* hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ IDirect3DSurface9_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX9(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ BYTE *pTempBitmap;
+ D3DCOLOR clBitmapOne, clBitmapZero;
+ D3DCOLOR *pBits;
+ const GLubyte *src;
+ int i, j, k;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // A NULL bitmap is valid, but merely advances the raster position
+ if ((bitmap == NULL) || (width == 0) || (height == 0))
+ return;
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pBits = (D3DCOLOR*)d3dLockedRect.pBits;
+
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch));
+ src = (const GLubyte *) _mesa_image_address(2,
+ &ctx->DefaultPacking, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ FREE(pTempBitmap);
+
+/*
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ GL_BITMAP,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack);
+*/
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ D3DFORMAT d3dFormat;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ D3DSURFACE_DESC d3dsd;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd));
+ // Release existing texture if not compatible
+ if ((d3dsd.Width == texImage->Width) ||
+ (d3dsd.Height == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX9_TEX(Release(pTex));
+ }
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ D3DXCreateTexture(
+ gld->pDev,
+ texImage->Width,
+ texImage->Height,
+ // TODO: Re-evaluate mipmapping
+ (glb.bUseMipmaps) ? D3DX_DEFAULT : 1,
+ 0, // Usage
+ d3dFormat,
+ D3DPOOL_MANAGED,
+ &pTex);
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(
+ ctx,
+ 2,
+ texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX9_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX9(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ if (tObj) {
+ IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX9_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DTEXTUREFILTERTYPE minfilter;
+ D3DTEXTUREFILTERTYPE mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirect3DTexture9 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ }
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX9(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE;
+ //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE;
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+#if 0
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+// GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ DWORD dwPasses;
+ _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses));
+// if (FAILED(hr)) {
+// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+// }
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
new file mode 100644
index 00000000000..4fa6bcaf1ab
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
@@ -0,0 +1,263 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx9 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX9_DEV(SetVertexShaderConstantF(gld->pDev, 0, (float*)&mat, 4));
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ tnl_render_func *tab;
+ GLint pass;
+ GLD_pb_dx9 *gldPB = &gld->PB3d;
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_TRUE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX9;
+ }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length)
+ {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection));
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_check(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ // Is this thread safe?
+ stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE;
+ return;
+}
+
+
+//---------------------------------------------------------------------------
+
+const struct tnl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
new file mode 100644
index 00000000000..372be2fb569
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
@@ -0,0 +1,444 @@
+/* $Id: gld_vb_mesa_render_dx9.c,v 1.6 2005-08-27 13:56:08 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 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.
+ *
+ * Authors:
+ * Keith Whitwell <[email protected]>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "mtypes.h"
+//#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+//#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+//#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+tnl_points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9
+};
+tnl_line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+};
+tnl_triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX9,
+ gld_Triangle2DSmooth_DX9,
+ gld_Triangle2DFlatExtras_DX9,
+ gld_Triangle2DSmoothExtras_DX9
+};
+tnl_quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX9,
+ gld_Quad2DSmooth_DX9,
+ gld_Quad2DFlatExtras_DX9,
+ gld_Quad2DSmoothExtras_DX9
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct tnl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx9 *gldPB;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets
+ // stream, indices and shader to default values of NULL or 0.
+/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) &&
+ gld->VStwosidelight.hShader &&
+ !ctx->Fog.Enabled)
+ {
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware);
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+ gldPB = &gld->PBtwosidelight;
+ tnl->Driver.Render.Points = gld_Points2DTwoside_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX9;
+ }
+ } else {*/
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, TRUE);
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+// }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_END) ; i += length) {
+ flags = VB->Primitive[i].mode;
+ length= VB->Primitive[i].count;
+ ASSERT(length || (flags & PRIM_END));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+
+const struct tnl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
new file mode 100644
index 00000000000..dc465c54185
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
@@ -0,0 +1,1345 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+#include "gld_dxerr9.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DFMT_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+*/
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+ HINSTANCE hD3D9DLL; // Handle to d3d9.dll
+ FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype
+ BOOL bDirect3D; // Persistant Direct3D9 exists
+ BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists
+ IDirect3D9 *pD3D; // Persistant Direct3D9
+ IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9
+} GLD_dx9_globals;
+
+// These are "global" to all DX9 contexts. KeithH
+static GLD_dx9_globals dx9Globals;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ const char *pStr = DXGetErrorString9(hr);
+
+ if (pStr == NULL)
+ return FALSE;
+
+ if (strlen(pStr) > nBufSize)
+ strncpy(buf, pStr, nBufSize);
+ else
+ strcpy(buf, pStr);
+
+// D3DXGetErrorString(hr, buf, nBufSize);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D9 *pD3D9,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx9 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx9 *lpCtx,
+ GLD_pb_dx9 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = MAX_ARRAY_LOCK_SIZE;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ hResult = IDirect3DDevice9_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+ gldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX9 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D9
+ // bPersistantBuffers: applies to IDirect3DDevice9
+ //
+
+ HRESULT hResult;
+ GLD_driver_dx9 *lpCtx = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ DWORD dwBehaviourFlags;
+ D3DADAPTER_IDENTIFIER9 d3dIdent;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ } else {
+ lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx9Globals.bDirect3D) {
+ lpCtx->pD3D = dx9Globals.pD3D;
+ IDirect3D9_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create Direct3D9 object
+ lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx9Globals.bDirect3D) {
+ dx9Globals.pD3D = lpCtx->pD3D;
+ IDirect3D9_AddRef(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Get device caps
+ hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+/*
+ //
+ // GONE FOR DX9?
+ //
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+*/
+
+ //
+ // Create the Direct3D context
+ //
+
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D9 as well
+ // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) {
+ lpCtx->pDev = dx9Globals.pDev;
+ IDirect3DDevice9_AddRef(dx9Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 2; //1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // PresentationInterval Windowed mode is optional now in DX9 (DaveM)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ // Add flag to tell D3D to be FPU-safe
+ if (!glb.bFastFPU)
+ dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
+ hResult = IDirect3D9_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) {
+ dx9Globals.pDev = lpCtx->pDev;
+ dx9Globals.bDirect3DDevice = TRUE;
+ }
+
+ // Dump some useful stats
+ hResult = IDirect3D9_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ 0, // No WHQL detection (avoid few seconds delay)
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+
+ // Test to see if IHV driver exposes Scissor Test (new for DX9)
+ lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST;
+ ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No");
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity(&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+ lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+ lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
+//DaveM D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
+ lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
+ lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
+ lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
+ if (FAILED(hResult))
+ goto return_with_error;*/
+
+ // Now try and create the DX9 Vertex Shaders
+// _gldCreateVertexShaders(lpCtx);
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx9 *gld = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hResult;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+
+ // Destroy DX9 Vertex Shaders before Reset()
+// _gldDestroyVertexShaders(gld);
+
+ // Release POOL_DEFAULT objects before Reset()
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
+// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+
+ //
+ // Recreate POOL_DEFAULT objects
+ //
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ }
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+ }
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
+// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+// }
+
+ // Recreate DX9 Vertex Shaders
+// _gldCreateVertexShaders(gld);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx9 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+ ZeroMemory(&dx9Globals, sizeof(dx9Globals));
+
+ // Load d3d9.dll
+ dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL");
+ if (dx9Globals.hD3D9DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate9
+ dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9");
+ if (dx9Globals.fnDirect3DCreate9 == NULL) {
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+ if (dx9Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx9Globals.pDev);
+ dx9Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx9Globals.bDirect3D) {
+ SAFE_RELEASE(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ dx9Globals.hD3D9DLL = NULL;
+ dx9Globals.fnDirect3DCreate9 = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+ case D3DFMT_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DFMT_D32:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D15S1:
+ *cDepthBits = 16;
+ *cStencilBits = 1;
+ return;
+ case D3DFMT_D24S8:
+ *cDepthBits = 32;
+ *cStencilBits = 8;
+ return;
+ case D3DFMT_D16:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X8:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X4S4:
+ *cDepthBits = 32;
+ *cStencilBits = 4;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DDISPLAYMODE d3ddm;
+ D3DFORMAT fmt[6];
+ IDirect3D9 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+ const D3DFORMAT DepthStencil[6] = {
+// New order: increaing Z, then increasing stencil
+ D3DFMT_D15S1,
+ D3DFMT_D16,
+ D3DFMT_D24X4S4,
+ D3DFMT_D24X8,
+ D3DFMT_D24S8,
+ D3DFMT_D32,
+ };
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ // Get a Direct3D 9.0 interface
+ pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (!pD3D) {
+ return FALSE;
+ }
+
+ // We will use the display mode format when finding compliant
+ // rendertarget/depth-stencil surfaces.
+ hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr)) {
+ IDirect3D9_Release(pD3D);
+ return FALSE;
+ }
+
+ // Run through the possible formats and detect supported formats
+ for (i=0; i<6; i++) {
+ hr = IDirect3D9_CheckDeviceFormat(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_SURFACE,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal.
+ continue;
+
+ // Verify that the depth format is compatible.
+ hr = IDirect3D9_CheckDepthStencilMatch(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ d3ddm.Format,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal, just means depth-stencil
+ // format is not compatible with this display mode.
+ continue;
+
+ fmt[nSupportedFormats++] = DepthStencil[i];
+ }
+
+ IDirect3D9_Release(pD3D);
+
+ if (nSupportedFormats == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ // UPDATED: nSupportedFormats*2
+ glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = nSupportedFormats*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+ _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ //
+ // Add single-buffer formats
+ //
+/*
+ // NOTE: No longer returning pixelformats that don't contain depth
+ // Single-buffer, no depth-stencil buffer
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+ // NOTE: No longer returning pixelformats that don't contain depth
+/*
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx9 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+ MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
+ }
+
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+// IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL);
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+ gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+//#endif
+
+ gldEnableExtensions_DX9(lpCtx->glCtx);
+ gldInstallPipeline_DX9(lpCtx->glCtx);
+ gldSetupDriverPointers_DX9(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx9 *gld = NULL;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+ hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+exit_swap:
+
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+// Debugging code
+#ifdef _DEBUG
+// ddlogMessage(GLDLOG_WARN, "SwapBuffers\n");
+#endif
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hr;
+ GLD_driver_dx9 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+ hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+ _BitsFromDisplayFormat(d3ddm.Format,
+ &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.Width;
+ glddm->Height = d3ddm.Height;
+ glddm->BPP = cColorBits;
+ glddm->Refresh = d3ddm.RefreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
index 1eb19ca84b0..3000cd07d2f 100644
--- a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
@@ -1,4 +1,4 @@
-/* $Id: gld_debug_clip.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+/* $Id: gld_debug_clip.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
index 00c428bd262..8b7523ff5f3 100644
--- a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
@@ -1,4 +1,4 @@
-/* $Id: gld_debug_norm.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+/* $Id: gld_debug_norm.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
index d6e64b8ffdf..5cbea2617ea 100644
--- a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
@@ -1,4 +1,4 @@
-/* $Id: gld_debug_xform.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+/* $Id: gld_debug_xform.c,v 1.1 2004-04-20 11:13:11 alanh Exp $ */
/*
* Mesa 3-D graphics library
diff --git a/src/mesa/drivers/windows/gldirect/gldirect.rc b/src/mesa/drivers/windows/gldirect/gldirect.rc
new file mode 100644
index 00000000000..ba09631538a
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gldirect.rc
@@ -0,0 +1,43 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: Windows Resource Compiler
+* Environment: Windows 95
+*
+****************************************************************************/
+
+#ifndef WORKSHOP_INVOKED
+ #include <windows.h>
+#endif
+
+#define FILE_DESCRIPTION "SciTech GLDirect"
+#define ORIG_FILENAME "opengl32.dll"
+#define FILE_TYPE VFT_DLL
+
+#include "gldirect/gldver.ver"
diff --git a/src/mesa/drivers/windows/gldirect/mesasw/colors.h b/src/mesa/drivers/windows/gldirect/mesasw/colors.h
new file mode 100644
index 00000000000..5660907aa51
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/mesasw/colors.h
@@ -0,0 +1,523 @@
+/* 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 : [email protected]
+ * 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
+ */
+
+/* $Log: ddcolors.h 1997/6/14 by Li Wei([email protected])
+ * Macros for pixel format defined
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004-04-20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * 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([email protected])
+ * Add LUTs need for dithering
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004-04-20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * 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([email protected])
+ * Add BGR8 Macro
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004-04-20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * 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([email protected])
+ * 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/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
new file mode 100644
index 00000000000..0f11b4fe513
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
@@ -0,0 +1,1719 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+* SCITECH SOFTWARE INC 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.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa Software WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include "glheader.h"
+#include "colors.h"
+#include "context.h"
+#include "colormac.h"
+#include "dd.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+//#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+DGL_pixelFormat pfTemplateMesaSW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 32, // Total colour bitplanes (excluding alpha bitplanes)
+ 8, 0, // Red bits, shift
+ 8, 8, // Green bits, shift
+ 8, 16, // Blue bits, shift
+ 8, 24, // Alpha bits, shift (destination alpha)
+ 64, // Accumulator bits (total)
+ 16, 16, 16, 16, // Accumulator bits: Red, Green, Blue, Alpha
+ 16, // Depth bits
+ 8, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ 0, // Unused
+};
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+static GLD_extension GLD_extList[] = {
+#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)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+// WMesa Internal Functions
+//---------------------------------------------------------------------------
+
+#define PAGE_FILE 0xffffffff
+
+#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 {
+ 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;
+
+ RECT rectOffScreen;
+ RECT rectSurface;
+// HWND hwnd;
+ DWORD pitch;
+ PBYTE addrOffScreen;
+
+ // We always double-buffer, for performance reasons, but
+ // we need to know which of SwapBuffers() or glFlush() to
+ // handle. If we're emulating, then we update on Flush(),
+ // otherwise we update on SwapBufers(). KeithH
+ BOOL bEmulateSingleBuffer;
+} WMesaContext, *PWMC;
+
+#define GLD_GET_WMESA_DRIVER(c) (WMesaContext*)(c)->glPriv
+
+// TODO:
+GLint stereo_flag = 0 ;
+
+/* If we are double-buffering, we want to get the DC for the
+ * off-screen DIB, otherwise the DC for the window.
+ */
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+#define DD_RELEASEDC
+
+#define FLIP(Y) (Current->height-(Y)-1)
+
+struct DISPLAY_OPTIONS {
+ int stereo;
+ int fullScreen;
+ int mode;
+ int bpp;
+};
+
+struct DISPLAY_OPTIONS displayOptions;
+
+//---------------------------------------------------------------------------
+
+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
+};
+
+//---------------------------------------------------------------------------
+
+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];
+}
+
+//---------------------------------------------------------------------------
+
+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 wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ WMesaContext *Current = pwc;
+
+ // Test for invalid scanline parameter. KeithH
+ if ((iScanLine < 0) || (iScanLine >= pwc->height))
+ return;
+
+ if (Current->db_flag) {
+ LPBYTE lpb = pwc->pbPixels;
+ UINT nBypp = pwc->cColorBits >> 3;
+ UINT nOffset = iPixel % nBypp;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ lpb += iPixel * nBypp;
+
+ 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)
+ *((LPWORD)lpb) = BGR16(r,g,b);
+ else if (nBypp == 3)
+ *((LPDWORD)lpb) = BGR24(r,g,b);
+ else if (nBypp == 4)
+ *((LPDWORD)lpb) = BGR32(r,g,b);
+ }
+ else{
+ SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // 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;
+ }
+
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : 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;
+
+}
+
+//---------------------------------------------------------------------------
+
+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);
+
+}
+
+//---------------------------------------------------------------------------
+
+/* This function sets the color table of a DIB section
+ * to match that of the destination DC
+ */
+BOOL 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;
+}
+
+//---------------------------------------------------------------------------
+
+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 creates the DIB section that is used for combined
+ * GL and GDI calls
+ */
+BOOL 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;
+ pwc->width = lxSize;
+ pwc->height = lySize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * 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;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Blit memory DC to screen DC
+ */
+BOOL wmFlush(PWMC pwc, HDC hDC)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+
+// Now using bEmulateSingleBuffer in the calling function. KeithH
+
+// if(pwc->db_flag){
+ bRet = BitBlt(hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+// }
+
+ return bRet;
+
+}
+
+//---------------------------------------------------------------------------
+// Support Functions
+//---------------------------------------------------------------------------
+
+static void flush(GLcontext* ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+/*
+ if((Current->rgb_flag &&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current, Current->hDC);
+ }
+*/
+ // Only flush if we're not in double-buffer mode. KeithH
+ // The demo fractal.c calls glutSwapBuffers() then glFlush()!
+ if (Current->bEmulateSingleBuffer) {
+ wmFlush(Current, Current->hDC);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ Current->clearpixel = index;
+}
+
+
+
+//---------------------------------------------------------------------------
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+//static void clear_color( GLcontext* ctx, const GLchan color[4] )
+// Changed for Mesa 5.x. KeithH
+static void clear_color(
+ GLcontext* ctx,
+ const GLfloat color[4])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ Current->clearpixel = RGB(col[0], col[1], col[2]);
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ * We also only clear the color buffers if the color masks are all 1's.
+ * Otherwise, we let swrast do it.
+ */
+
+static clear(GLcontext* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+
+
+ /* sanity check - can't have right(stereo) buffers */
+ assert((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT)) == 0);
+
+ /* clear alpha */
+ if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_RIGHT_BIT)) &&
+ ctx->DrawBuffer->UseSoftwareAlphaBuffers &&
+ ctx->Color.ColorMask[ACOMP]) {
+ _swrast_clear_alpha_buffers( ctx );
+ }
+
+ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+ if (mask & DD_BACK_LEFT_BIT) {
+ /* Double-buffering - clear back buffer */
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+
+ assert(Current->db_flag==GL_TRUE); /* we'd better be double buffer */
+ if(nBypp ==1 ){
+ 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));
+ }
+
+ /* clear a line */
+ 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;
+ /* copy cleared line to other lines in buffer */
+ do {
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ mask &= ~DD_BACK_LEFT_BIT;
+ } /* double-buffer */
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ /* 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;
+ mask &= ~DD_FRONT_LEFT_BIT;
+ } /* single-buffer */
+ } /* if masks are all 1's */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+
+//---------------------------------------------------------------------------
+
+
+static void enable( GLcontext* ctx, GLenum pname, GLboolean enable )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+
+ if (!Current)
+ return;
+
+ if (pname == GL_DITHER) {
+ 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_draw_buffer( GLcontext* ctx, GLenum mode )
+{
+ /* TODO: this could be better */
+ if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+
+static void set_read_buffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+ GLenum buffer )
+{
+ /* XXX todo */
+ return;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* Return characteristics of the output buffer. */
+//static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height )
+// Altered for Mesa 5.x. KeithH
+static void buffer_size(
+ GLframebuffer *buffer,
+ GLuint *width,
+ GLuint *height)
+{
+ // For some reason the context is not passed into this function.
+ // Therefore we have to explicitly retrieve it.
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ int New_Size;
+ RECT CR;
+
+ 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){
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+ }
+
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+/* Accelerated routines are not implemented in 4.0. See OSMesa for ideas. */
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+}
+
+//---------------------------------------------------------------------------
+
+/* Return pointer to accelerated points function */
+extern tnl_points_func choose_points_function( GLcontext* ctx )
+{
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0,
+ GLuint v1, GLuint pv )
+{
+}
+
+//---------------------------------------------------------------------------
+
+static tnl_line_func choose_line_function( GLcontext* ctx )
+{
+}
+
+
+/**********************************************************************/
+/***** 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[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */
+static void write_ci8_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current
+ * color index is used for all pixels.
+ */
+static void write_mono_ci_span(const GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ GLuint colorIndex, const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=colorIndex;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * 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[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* 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[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * 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 GLchan color[4], const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ ULONG pixel = RGB( color[RCOMP], color[GCOMP], color[BCOMP] );
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc,y,x+i,color[RCOMP], color[GCOMP], color[BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, pixel);
+ }
+ DD_RELEASEDC;
+}
+
+
+
+/**********************************************************************/
+/***** 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[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * 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[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = colorIndex;
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* 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[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ DD_RELEASEDC;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+ DD_RELEASEDC;
+}
+
+/**********************************************************************/
+/***** 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[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y = Current->height - y - 1;
+ for (i=0; i<n; i++) {
+ Color=GetPixel(DC,x+i,y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLint y2 = Current->height - y[i] - 1;
+ Color=GetPixel(DC,x[i],y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_viewport(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+// ctx->Driver.ResizeBuffersMESA(ctx);
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state_first_time(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /*
+ * XXX these function pointers could be initialized just once during
+ * context creation since they don't depend on any state changes.
+ * kws - This is true - this function gets called a lot and it
+ * would be good to minimize setting all this when not needed.
+ */
+ // Good idea, so I'll do it. KeithH. :-)
+
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = wmesa_update_state;
+ ctx->Driver.DrawBuffer = set_draw_buffer;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.Viewport = wmesa_viewport;
+
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Flush = flush;
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Enable = enable;
+
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+ ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
+ ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+ ctx->Driver.TexImage2D = _mesa_store_teximage2d;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
+ ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ // Does not apply for Mesa 5.x
+ //ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat;
+ //ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size;
+ //ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage;
+
+ swdd->SetBuffer = set_read_buffer;
+
+
+ /* Pixel/span writing functions: */
+ swdd->WriteRGBASpan = write_rgba_span;
+ swdd->WriteRGBSpan = write_rgb_span;
+ swdd->WriteMonoRGBASpan = write_mono_rgba_span;
+ swdd->WriteRGBAPixels = write_rgba_pixels;
+ swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ swdd->WriteCI32Span = write_ci32_span;
+ swdd->WriteCI8Span = write_ci8_span;
+ swdd->WriteMonoCISpan = write_mono_ci_span;
+ swdd->WriteCI32Pixels = write_ci32_pixels;
+ swdd->WriteMonoCIPixels = write_mono_ci_pixels;
+
+ swdd->ReadCI32Span = read_ci32_span;
+ swdd->ReadRGBASpan = read_rgba_span;
+ swdd->ReadCI32Pixels = read_ci32_pixels;
+ swdd->ReadRGBAPixels = read_rgba_pixels;
+
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ wmesa_update_state(ctx, new_state);
+}
+
+//---------------------------------------------------------------------------
+// Driver interface functions
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_MesaSW(
+ DGL_ctx *pCtx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+ GLboolean true_color_flag;
+ GLboolean rgb_flag = GL_TRUE;
+ GLboolean db_flag = GL_TRUE;
+
+ if (pCtx == NULL)
+ return FALSE;
+
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return FALSE;
+
+ pCtx->glPriv = c;
+
+ c->hDC = pCtx->hDC;
+ c->Window = pCtx->hWnd;
+
+ true_color_flag = GetDeviceCaps(pCtx->hDC, BITSPIXEL) > 8;
+
+
+#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;
+#if 0
+ /* Old WinG stuff???? */
+ 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");
+#endif
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ }
+
+// db_flag = pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? GL_TRUE : GL_FALSE;
+ db_flag = GL_TRUE; // Force double-buffer
+ if (db_flag) {
+ c->db_flag = 1;
+ /* Double buffered */
+ {
+ wmCreateBackingStore(c, pCtx->dwWidth, pCtx->dwHeight);
+
+ }
+ } else {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+
+ c->bEmulateSingleBuffer = (pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER)
+ ? FALSE : TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_MesaSW(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ c->hDC = ctx->hDC;
+ c->Window = ctx->hWnd;
+// c->width = ctx->dwWidth;
+// c->height = ctx->dwHeight;
+
+ if (c->db_flag) {
+ wmDeleteBackingStore(c);
+ wmCreateBackingStore(c, ctx->dwWidth, ctx->dwHeight);
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_MesaSW(
+ DGL_ctx *ctx)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ if (c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+
+ if (c->db_flag)
+ wmDeleteBackingStore(c);
+
+ free(c);
+
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_MesaSW(void)
+{
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ glb.lpPF = (DGL_pixelFormat *)calloc(2, sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ return FALSE;
+ // Single-buffered
+ memcpy(&glb.lpPF[0], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.lpPF[0].pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ // Double-buffered
+ memcpy(&glb.lpPF[1], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = 2;
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_MesaSW(
+ DGL_ctx *gld)
+{
+ GLcontext *ctx;
+
+ if (gld == NULL)
+ return FALSE;
+
+ ctx = gld->glCtx;
+
+ // Set max texture size to 256
+ ctx->Const.MaxTextureLevels = 8;
+
+ // Multitexture enable/disable
+ ctx->Const.MaxTextureUnits = (glb.bMultitexture) ? MAX_TEXTURE_UNITS : 1;
+
+ /* Initialize the software rasterizer and helper modules.*/
+
+ // Added this to force max texture diminsion to 256. KeithH
+ ctx->Const.MaxTextureLevels = 8;
+
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+
+// _swrast_CreateContext( ctx );
+// _ac_CreateContext( ctx );
+// _tnl_CreateContext( ctx );
+// _swsetup_CreateContext( ctx );
+
+ _swsetup_Wakeup( ctx );
+
+ wmesa_update_state_first_time(ctx, ~0);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_MesaSW(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+
+ // Altered to respect bEmulateSingleBuffer. KeithH
+// if (c->db_flag)
+ if (!c->bEmulateSingleBuffer)
+ wmFlush(c, hDC);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_MesaSW(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_MesaSW(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ HDC hdcDesktop;
+
+ if (glddm == NULL)
+ return FALSE;
+
+ //
+ // A bit hacky... KeithH
+ //
+
+ hdcDesktop = GetDC(NULL);
+ glddm->Width = GetDeviceCaps(hdcDesktop, HORZRES);
+ glddm->Height = GetDeviceCaps(hdcDesktop, VERTRES);
+ glddm->BPP = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ glddm->Refresh = 0;
+ ReleaseDC(0, hdcDesktop);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/opengl32.ref b/src/mesa/drivers/windows/gldirect/opengl32.ref
new file mode 100644
index 00000000000..2f71faf2167
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/opengl32.ref
@@ -0,0 +1,495 @@
+;****************************************************************************
+;*
+;* Mesa 3-D graphics library
+;* Direct3D Driver Interface
+;*
+;* ========================================================================
+;*
+;* Copyright (C) 1991-2004 SciTech Software, Inc. 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
+;* SCITECH SOFTWARE INC 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.
+;*
+;* ======================================================================
+;*
+;* Language: ANSI C
+;* Environment: Windows 9x/2000/XP/XBox (Win32)
+;*
+;* Description: DLL Module definition file
+;*
+;****************************************************************************/
+
+DESCRIPTION 'GLDirect'
+
+VERSION 3.0
+
+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
+
+;These functions are identical and therefore share the same addresses
+ ChoosePixelFormat = wglChoosePixelFormat
+ DescribePixelFormat = wglDescribePixelFormat
+ GetPixelFormat = wglGetPixelFormat
+ SetPixelFormat = wglSetPixelFormat
+ SwapBuffers = wglSwapBuffers
+
+ wglChoosePixelFormat
+ wglDescribePixelFormat
+ wglGetPixelFormat
+ wglSetPixelFormat
+ wglSwapBuffers
+
+ 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
diff --git a/src/mesa/drivers/x11/xm_buffer.c b/src/mesa/drivers/x11/xm_buffer.c
index 2f20b162a7f..2a44e126f78 100644
--- a/src/mesa/drivers/x11/xm_buffer.c
+++ b/src/mesa/drivers/x11/xm_buffer.c
@@ -48,7 +48,7 @@ static GLboolean
xmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
/* just clear these to be sure we don't accidentally use them */
xrb->origin1 = NULL;
@@ -74,7 +74,7 @@ static GLboolean
xmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
GLenum internalFormat, GLuint width, GLuint height)
{
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
/* same as front buffer */
(void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height);
diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c
index 516b238d6eb..d339ac6bc39 100644
--- a/src/mesa/drivers/x11/xm_dd.c
+++ b/src/mesa/drivers/x11/xm_dd.c
@@ -302,11 +302,12 @@ clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
if (all) {
- GLint i, c16 = (xrb->ximage->bytes_per_line>>4)<<4;
+ const GLuint c16 = xrb->ximage->bytes_per_line & ~0xf;
+ GLuint i;
GLubyte *ptr = (GLubyte *) xrb->ximage->data;
for (i = 0; i < xrb->Base.Height; i++) {
- GLint j;
- GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
+ GLuint j;
+ const GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
if (i&1) {
sptr += 16;
}
@@ -329,7 +330,7 @@ clear_HPCR_ximage( GLcontext *ctx, struct xmesa_renderbuffer *xrb,
ptr[15] = sptr[15];
ptr += 16;
}
- for (; j < xrb->ximage->bytes_per_line; j++) {
+ for (; j < (GLuint) xrb->ximage->bytes_per_line; j++) {
*ptr = sptr[j&15];
ptr++;
}
@@ -530,14 +531,15 @@ clear_buffers( GLcontext *ctx, GLbitfield mask,
if (ctx->DrawBuffer->Name == 0) {
/* this is a window system framebuffer */
const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
- XMesaBuffer b = (XMesaBuffer) ctx->DrawBuffer;
+ XMesaBuffer b = XMESA_BUFFER(ctx->DrawBuffer);
/* we can't handle color or index masking */
if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
if (mask & BUFFER_BIT_FRONT_LEFT) {
/* clear front color buffer */
- if (b->frontxrb == (struct xmesa_renderbuffer *)
- ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *frontRb
+ = ctx->DrawBuffer->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
+ if (b->frontxrb == xmesa_renderbuffer(frontRb)) {
/* renderbuffer is not wrapped - great! */
b->frontxrb->clearFunc(ctx, b->frontxrb, all, x, y,
width, height);
@@ -549,8 +551,9 @@ clear_buffers( GLcontext *ctx, GLbitfield mask,
}
if (mask & BUFFER_BIT_BACK_LEFT) {
/* clear back color buffer */
- if (b->backxrb == (struct xmesa_renderbuffer *)
- ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer) {
+ struct gl_renderbuffer *backRb
+ = ctx->DrawBuffer->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
+ if (b->backxrb == xmesa_renderbuffer(backRb)) {
/* renderbuffer is not wrapped - great! */
b->backxrb->clearFunc(ctx, b->backxrb, all, x, y,
width, height);
@@ -600,7 +603,7 @@ xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
const GLvoid *pixels )
{
struct xmesa_renderbuffer *xrb
- = (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0];
+ = (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const SWcontext *swrast = SWRAST_CONTEXT( ctx );
@@ -997,18 +1000,18 @@ xmesa_update_state( GLcontext *ctx, GLbitfield new_state )
* renderbuffer span/clear funcs.
*/
if (new_state & (_NEW_COLOR | _NEW_PIXEL | _NEW_BUFFERS)) {
+ XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
struct xmesa_renderbuffer *front_xrb, *back_xrb;
- front_xrb = XMESA_BUFFER(ctx->DrawBuffer)->frontxrb;
+ front_xrb = xmbuf->frontxrb;
if (front_xrb) {
xmesa_set_renderbuffer_funcs(front_xrb, xmesa->pixelformat,
xmesa->xm_visual->BitsPerPixel);
front_xrb->clearFunc = clear_pixmap;
}
- back_xrb = XMESA_BUFFER(ctx->DrawBuffer)->backxrb;
+ back_xrb = xmbuf->backxrb;
if (back_xrb) {
- XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
xmesa_set_renderbuffer_funcs(back_xrb, xmesa->pixelformat,
xmesa->xm_visual->BitsPerPixel);
if (xmbuf->backxrb->pixmap) {
@@ -1151,10 +1154,15 @@ update_framebuffer_size(GLcontext *ctx)
* Thus, we poll.
* Note that this trick isn't fool-proof. If the application never calls
* glViewport, our notion of the current window size may be incorrect.
+ * That problem led to the GLX_MESA_resize_buffers extension.
*/
static void
xmesa_viewport(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
{
+ (void) x;
+ (void) y;
+ (void) w;
+ (void) h;
update_framebuffer_size(ctx);
}
diff --git a/src/mesa/drivers/x11/xm_line.c b/src/mesa/drivers/x11/xm_line.c
index f60ffa65eb9..c3105425159 100644
--- a/src/mesa/drivers/x11/xm_line.c
+++ b/src/mesa/drivers/x11/xm_line.c
@@ -117,8 +117,11 @@ void xmesa_choose_point( GLcontext *ctx )
/**********************************************************************/
+#if CHAN_BITS == 8
+
+
#define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \
- (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped
+ xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped)
/*
@@ -533,6 +536,7 @@ void xmesa_choose_point( GLcontext *ctx )
+
#ifndef XFree86Server
/**
* Draw fast, XOR line with XDrawLine in front color buffer.
@@ -547,8 +551,7 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaGC gc = xmesa->xm_buffer->gc;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *)
- ctx->DrawBuffer->_ColorDrawBuffers[0][0];
+ GET_XRB(xrb);
unsigned long pixel = xmesa_color_to_pixel(ctx,
vert1->color[0], vert1->color[1],
vert1->color[2], vert1->color[3],
@@ -567,6 +570,9 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
#endif /* XFree86Server */
+#endif /* CHAN_BITS == 8 */
+
+
/**
* Return pointer to line drawing function, or NULL if we should use a
* swrast fallback.
@@ -574,11 +580,15 @@ xor_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
static swrast_line_func
get_line_func(GLcontext *ctx)
{
+#if CHAN_BITS == 8
XMesaContext xmesa = XMESA_CONTEXT(ctx);
SWcontext *swrast = SWRAST_CONTEXT(ctx);
int depth = GET_VISUAL_DEPTH(xmesa->xm_visual);
struct xmesa_renderbuffer *xrb;
+ if (CHAN_BITS != 8)
+ return NULL;
+
if ((ctx->DrawBuffer->_ColorDrawBufferMask[0]
& (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0)
return (swrast_line_func) NULL;
@@ -589,8 +599,7 @@ get_line_func(GLcontext *ctx)
if (ctx->Line.StippleFlag) return (swrast_line_func) NULL;
if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL;
- xrb = (struct xmesa_renderbuffer *)
- ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped;
+ xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
if (xrb->ximage
&& swrast->_RasterMask==DEPTH_BIT
@@ -663,6 +672,7 @@ get_line_func(GLcontext *ctx)
}
#endif /* XFree86Server */
+#endif /* CHAN_BITS == 8 */
return (swrast_line_func) NULL;
}
diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c
index 664f365df96..ff0557800ae 100644
--- a/src/mesa/drivers/x11/xm_span.c
+++ b/src/mesa/drivers/x11/xm_span.c
@@ -21,7 +21,6 @@
* 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.
*/
-/* $XFree86: xc/extras/Mesa/src/X/xm_span.c,v 1.3 2002/02/27 21:07:54 tsi Exp $ */
#include "glxheader.h"
#include "colormac.h"
@@ -176,7 +175,8 @@ static unsigned long read_pixel( XMesaDisplay *dpy,
const void *values, const GLubyte mask[]
-/* NOTE: if mask==NULL, draw all pixels */
+#define GET_XRB(XRB) \
+ struct xmesa_renderbuffer *XRB = xmesa_renderbuffer(rb)
/*
@@ -186,7 +186,7 @@ static void put_row_TRUECOLOR_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = XMESA_BUFFER(ctx->DrawBuffer)->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -223,7 +223,7 @@ static void put_row_rgb_TRUECOLOR_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -258,7 +258,7 @@ static void put_row_TRUEDITHER_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -293,7 +293,7 @@ static void put_row_rgb_TRUEDITHER_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -328,7 +328,7 @@ static void put_row_8A8B8G8R_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -362,7 +362,7 @@ static void put_row_rgb_8A8B8G8R_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -395,7 +395,7 @@ static void put_row_8A8R8G8B_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -429,7 +429,7 @@ static void put_row_rgb_8A8R8G8B_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -462,7 +462,7 @@ static void put_row_8R8G8B_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -495,7 +495,7 @@ static void put_row_8R8G8B24_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -591,7 +591,7 @@ static void put_row_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -623,7 +623,7 @@ static void put_row_rgb_8R8G8B24_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -724,7 +724,7 @@ static void put_row_5R6G5B_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -757,7 +757,7 @@ static void put_row_DITHER_5R6G5B_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -792,7 +792,7 @@ static void put_row_rgb_5R6G5B_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -825,7 +825,7 @@ static void put_row_rgb_DITHER_5R6G5B_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -860,7 +860,7 @@ static void put_row_DITHER_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -893,7 +893,7 @@ static void put_row_rgb_DITHER_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -926,7 +926,7 @@ static void put_row_1BIT_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -961,7 +961,7 @@ static void put_row_rgb_1BIT_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -996,7 +996,7 @@ static void put_row_HPCR_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1029,7 +1029,7 @@ static void put_row_rgb_HPCR_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1061,7 +1061,7 @@ static void put_row_LOOKUP_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1093,7 +1093,7 @@ static void put_row_rgb_LOOKUP_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1125,7 +1125,7 @@ static void put_row_GRAYSCALE_pixmap( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1156,7 +1156,7 @@ static void put_row_rgb_GRAYSCALE_pixmap( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -1186,7 +1186,7 @@ static void put_row_TRUECOLOR_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -1217,7 +1217,7 @@ static void put_row_rgb_TRUECOLOR_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -1248,7 +1248,7 @@ static void put_row_TRUEDITHER_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -1279,7 +1279,7 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -1309,9 +1309,10 @@ static void put_row_rgb_TRUEDITHER_ximage( RGB_SPAN_ARGS )
static void put_row_8A8B8G8R_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
+ (void) ctx;
if (mask) {
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -1334,7 +1335,7 @@ static void put_row_8A8B8G8R_ximage( PUT_ROW_ARGS )
static void put_row_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
if (mask) {
@@ -1358,7 +1359,7 @@ static void put_row_rgb_8A8B8G8R_ximage( RGB_SPAN_ARGS )
static void put_row_8A8R8G8B_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
if (mask) {
@@ -1383,7 +1384,7 @@ static void put_row_8A8R8G8B_ximage( PUT_ROW_ARGS )
static void put_row_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
if (mask) {
@@ -1408,7 +1409,7 @@ static void put_row_rgb_8A8R8G8B_ximage( RGB_SPAN_ARGS )
static void put_row_8R8G8B_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
if (mask) {
@@ -1432,7 +1433,7 @@ static void put_row_8R8G8B_ximage( PUT_ROW_ARGS )
static void put_row_8R8G8B24_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y );
if (mask) {
@@ -1583,7 +1584,7 @@ static void put_row_8R8G8B24_ximage( PUT_ROW_ARGS )
static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLuint *ptr = PIXEL_ADDR4(xrb, x, y);
if (mask) {
@@ -1608,7 +1609,7 @@ static void put_row_rgb_8R8G8B_ximage( RGB_SPAN_ARGS )
static void put_row_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = (GLubyte *) PIXEL_ADDR3(xrb, x, y);
if (mask) {
@@ -1640,7 +1641,7 @@ static void put_row_rgb_8R8G8B24_ximage( RGB_SPAN_ARGS )
static void put_row_5R6G5B_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
if (mask) {
@@ -1680,7 +1681,7 @@ static void put_row_5R6G5B_ximage( PUT_ROW_ARGS )
static void put_row_DITHER_5R6G5B_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
@@ -1722,7 +1723,7 @@ static void put_row_DITHER_5R6G5B_ximage( PUT_ROW_ARGS )
static void put_row_rgb_5R6G5B_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLushort *ptr = PIXEL_ADDR2(xrb, x, y);
if (mask) {
@@ -1762,7 +1763,7 @@ static void put_row_rgb_5R6G5B_ximage( RGB_SPAN_ARGS )
static void put_row_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
register GLushort *ptr = PIXEL_ADDR2(xrb, x, y );
@@ -1803,7 +1804,7 @@ static void put_row_rgb_DITHER_5R6G5B_ximage( RGB_SPAN_ARGS )
static void put_row_DITHER_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
int yy = YFLIP(xrb, y);
@@ -1830,7 +1831,7 @@ static void put_row_DITHER_ximage( PUT_ROW_ARGS )
static void put_row_rgb_DITHER_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
int yy = YFLIP(xrb, y);
@@ -1858,7 +1859,7 @@ static void put_row_rgb_DITHER_ximage( RGB_SPAN_ARGS )
static void put_row_DITHER8_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
XDITHER_SETUP(y);
@@ -1880,7 +1881,7 @@ static void put_row_DITHER8_ximage( PUT_ROW_ARGS )
static void put_row_rgb_DITHER8_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
XDITHER_SETUP(y);
@@ -1909,7 +1910,7 @@ static void put_row_1BIT_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
SETUP_1BIT;
@@ -1936,7 +1937,7 @@ static void put_row_rgb_1BIT_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
SETUP_1BIT;
@@ -1962,7 +1963,7 @@ static void put_row_rgb_1BIT_ximage( RGB_SPAN_ARGS )
static void put_row_HPCR_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
@@ -1988,7 +1989,7 @@ static void put_row_HPCR_ximage( PUT_ROW_ARGS )
static void put_row_rgb_HPCR_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
@@ -2014,7 +2015,7 @@ static void put_row_rgb_HPCR_ximage( RGB_SPAN_ARGS )
static void put_row_LOOKUP_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
LOOKUP_SETUP;
@@ -2041,7 +2042,7 @@ static void put_row_LOOKUP_ximage( PUT_ROW_ARGS )
static void put_row_rgb_LOOKUP_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
LOOKUP_SETUP;
@@ -2068,7 +2069,7 @@ static void put_row_rgb_LOOKUP_ximage( RGB_SPAN_ARGS )
static void put_row_LOOKUP8_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
LOOKUP_SETUP;
@@ -2091,7 +2092,7 @@ static void put_row_LOOKUP8_ximage( PUT_ROW_ARGS )
static void put_row_rgb_LOOKUP8_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
LOOKUP_SETUP;
@@ -2119,7 +2120,7 @@ static void put_row_rgb_LOOKUP8_ximage( RGB_SPAN_ARGS )
static void put_row_GRAYSCALE_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -2145,7 +2146,7 @@ static void put_row_GRAYSCALE_ximage( PUT_ROW_ARGS )
static void put_row_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -2171,7 +2172,7 @@ static void put_row_rgb_GRAYSCALE_ximage( RGB_SPAN_ARGS )
static void put_row_GRAYSCALE8_ximage( PUT_ROW_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
if (mask) {
@@ -2196,7 +2197,7 @@ static void put_row_GRAYSCALE8_ximage( PUT_ROW_ARGS )
static void put_row_rgb_GRAYSCALE8_ximage( RGB_SPAN_ARGS )
{
const GLubyte (*rgb)[3] = (const GLubyte (*)[3]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
if (mask) {
@@ -2235,7 +2236,7 @@ static void put_values_TRUECOLOR_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2258,7 +2259,7 @@ static void put_values_TRUEDITHER_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2281,7 +2282,7 @@ static void put_values_8A8B8G8R_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2302,7 +2303,7 @@ static void put_values_8A8R8G8B_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2323,7 +2324,7 @@ static void put_values_8R8G8B_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2344,7 +2345,7 @@ static void put_values_8R8G8B24_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2365,7 +2366,7 @@ static void put_values_5R6G5B_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2386,7 +2387,7 @@ static void put_values_DITHER_5R6G5B_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2409,7 +2410,7 @@ static void put_values_DITHER_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2432,7 +2433,7 @@ static void put_values_1BIT_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2455,7 +2456,7 @@ static void put_values_HPCR_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2477,7 +2478,7 @@ static void put_values_LOOKUP_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2499,7 +2500,7 @@ static void put_values_GRAYSCALE_pixmap( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2520,7 +2521,7 @@ static void put_values_TRUECOLOR_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
for (i=0;i<n;i++) {
@@ -2540,7 +2541,7 @@ static void put_values_TRUEDITHER_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
for (i=0;i<n;i++) {
@@ -2559,7 +2560,7 @@ static void put_values_TRUEDITHER_ximage( PUT_VALUES_ARGS )
static void put_values_8A8B8G8R_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2575,7 +2576,7 @@ static void put_values_8A8B8G8R_ximage( PUT_VALUES_ARGS )
static void put_values_8A8R8G8B_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2592,7 +2593,7 @@ static void put_values_8A8R8G8B_ximage( PUT_VALUES_ARGS )
static void put_values_8R8G8B_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2609,7 +2610,7 @@ static void put_values_8R8G8B_ximage( PUT_VALUES_ARGS )
static void put_values_8R8G8B24_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2628,7 +2629,7 @@ static void put_values_8R8G8B24_ximage( PUT_VALUES_ARGS )
static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2645,7 +2646,7 @@ static void put_values_5R6G5B_ximage( PUT_VALUES_ARGS )
static void put_values_DITHER_5R6G5B_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
for (i=0;i<n;i++) {
@@ -2663,7 +2664,7 @@ static void put_values_DITHER_5R6G5B_ximage( PUT_VALUES_ARGS )
static void put_values_DITHER_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
DITHER_SETUP;
@@ -2682,7 +2683,7 @@ static void put_values_DITHER_ximage( PUT_VALUES_ARGS )
static void put_values_DITHER8_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
DITHER_SETUP;
for (i=0;i<n;i++) {
@@ -2701,7 +2702,7 @@ static void put_values_1BIT_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
SETUP_1BIT;
@@ -2720,7 +2721,7 @@ static void put_values_1BIT_ximage( PUT_VALUES_ARGS )
static void put_values_HPCR_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLuint i;
for (i=0;i<n;i++) {
@@ -2738,7 +2739,7 @@ static void put_values_HPCR_ximage( PUT_VALUES_ARGS )
static void put_values_LOOKUP_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
LOOKUP_SETUP;
@@ -2756,7 +2757,7 @@ static void put_values_LOOKUP_ximage( PUT_VALUES_ARGS )
static void put_values_LOOKUP8_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
LOOKUP_SETUP;
for (i=0;i<n;i++) {
@@ -2774,7 +2775,7 @@ static void put_values_LOOKUP8_ximage( PUT_VALUES_ARGS )
static void put_values_GRAYSCALE_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
for (i=0;i<n;i++) {
@@ -2792,7 +2793,7 @@ static void put_values_GRAYSCALE_ximage( PUT_VALUES_ARGS )
static void put_values_GRAYSCALE8_ximage( PUT_VALUES_ARGS )
{
const GLubyte (*rgba)[4] = (const GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
for (i=0;i<n;i++) {
if (mask[i]) {
@@ -2822,7 +2823,7 @@ static void put_values_GRAYSCALE8_ximage( PUT_VALUES_ARGS )
static void put_mono_row_pixmap( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
@@ -2863,7 +2864,7 @@ put_mono_row_ci_pixmap( PUT_MONO_ROW_ARGS )
{
GLuint colorIndex = *((GLuint *) value);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -2899,7 +2900,7 @@ put_mono_row_ci_pixmap( PUT_MONO_ROW_ARGS )
static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
@@ -2924,7 +2925,7 @@ static void put_mono_row_TRUEDITHER_pixmap( PUT_MONO_ROW_ARGS )
static void put_mono_row_DITHER_pixmap( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
@@ -2948,7 +2949,7 @@ static void put_mono_row_DITHER_pixmap( PUT_MONO_ROW_ARGS )
static void put_mono_row_1BIT_pixmap( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
@@ -2972,7 +2973,7 @@ static void put_mono_row_1BIT_pixmap( PUT_MONO_ROW_ARGS )
static void put_mono_row_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaImage *img = xrb->ximage;
register GLuint i;
@@ -2991,7 +2992,7 @@ static void
put_mono_row_ci_ximage( PUT_MONO_ROW_ARGS )
{
const GLuint colorIndex = *((GLuint *) value);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -3009,7 +3010,7 @@ put_mono_row_ci_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_TRUEDITHER_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaImage *img = xrb->ximage;
const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
@@ -3031,7 +3032,7 @@ static void put_mono_row_TRUEDITHER_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_8A8B8G8R_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaContext xmesa = XMESA_CONTEXT(ctx);
GLuint i, *ptr;
const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
@@ -3050,7 +3051,7 @@ static void put_mono_row_8A8B8G8R_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_8A8R8G8B_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
GLuint i, *ptr;
XMesaContext xmesa = XMESA_CONTEXT(ctx);
const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
@@ -3070,7 +3071,7 @@ static void put_mono_row_8A8R8G8B_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_8R8G8B_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLuint pixel = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
GLuint *ptr = PIXEL_ADDR4(xrb, x, y );
GLuint i;
@@ -3088,7 +3089,7 @@ static void put_mono_row_8R8G8B_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_8R8G8B24_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP];
const GLubyte g = color[GCOMP];
const GLubyte b = color[BCOMP];
@@ -3110,7 +3111,7 @@ static void put_mono_row_8R8G8B24_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_DITHER_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
XMesaImage *img = xrb->ximage;
int yy = YFLIP(xrb, y);
@@ -3130,7 +3131,7 @@ static void put_mono_row_DITHER_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_DITHER8_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
register GLuint i;
@@ -3149,7 +3150,7 @@ static void put_mono_row_DITHER8_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_LOOKUP8_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
GLubyte pixel;
@@ -3170,7 +3171,7 @@ static void put_mono_row_1BIT_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
XMesaImage *img = xrb->ximage;
register GLuint i;
@@ -3190,7 +3191,7 @@ static void put_mono_row_1BIT_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_HPCR_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLubyte *ptr = PIXEL_ADDR1(xrb, x, y);
@@ -3209,7 +3210,7 @@ static void put_mono_row_HPCR_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_GRAYSCALE8_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
GLubyte *ptr = (GLubyte *) PIXEL_ADDR1(xrb, x, y);
GLuint i;
@@ -3228,7 +3229,7 @@ static void put_mono_row_GRAYSCALE8_ximage( PUT_MONO_ROW_ARGS )
static void put_mono_row_DITHER_5R6G5B_ximage( PUT_MONO_ROW_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
register GLushort *ptr = PIXEL_ADDR2(xrb, x, y );
const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
@@ -3261,7 +3262,7 @@ static void put_mono_values_pixmap( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3283,7 +3284,7 @@ put_mono_values_ci_pixmap( PUT_MONO_VALUES_ARGS )
{
const GLuint colorIndex = *((GLuint *) value);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3305,7 +3306,7 @@ static void put_mono_values_TRUEDITHER_pixmap( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3330,7 +3331,7 @@ static void put_mono_values_DITHER_pixmap( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3353,7 +3354,7 @@ static void put_mono_values_1BIT_pixmap( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3376,7 +3377,7 @@ static void put_mono_values_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
const unsigned long pixel = xmesa_color_to_pixel(ctx, color[RCOMP],
@@ -3393,7 +3394,7 @@ static void
put_mono_values_ci_ximage( PUT_MONO_VALUES_ARGS )
{
const GLuint colorIndex = *((GLuint *) value);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
for (i=0;i<n;i++) {
@@ -3411,7 +3412,7 @@ static void put_mono_values_TRUEDITHER_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
@@ -3432,7 +3433,7 @@ static void put_mono_values_TRUEDITHER_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_8A8B8G8R_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLuint p = PACK_8A8B8G8R(color[RCOMP], color[GCOMP],
color[BCOMP], color[ACOMP]);
register GLuint i;
@@ -3450,7 +3451,7 @@ static void put_mono_values_8A8B8G8R_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_8A8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLuint p = PACK_8A8R8G8B(color[RCOMP], color[GCOMP],
color[BCOMP], color[ACOMP]);
register GLuint i;
@@ -3468,7 +3469,7 @@ static void put_mono_values_8A8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
const GLuint p = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]);
for (i=0;i<n;i++) {
@@ -3486,7 +3487,7 @@ static void put_mono_values_8R8G8B_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_8R8G8B24_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLuint i;
for (i=0;i<n;i++) {
@@ -3506,7 +3507,7 @@ static void put_mono_values_8R8G8B24_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_DITHER_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
XMesaImage *img = xrb->ximage;
register GLuint i;
@@ -3525,7 +3526,7 @@ static void put_mono_values_DITHER_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_DITHER8_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLuint i;
DITHER_SETUP;
@@ -3544,7 +3545,7 @@ static void put_mono_values_DITHER8_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_LOOKUP8_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
GLubyte pixel;
LOOKUP_SETUP;
@@ -3566,7 +3567,7 @@ static void put_mono_values_1BIT_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
XMesaImage *img = xrb->ximage;
register GLuint i;
@@ -3586,7 +3587,7 @@ static void put_mono_values_1BIT_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_HPCR_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLuint i;
@@ -3605,7 +3606,7 @@ static void put_mono_values_HPCR_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_GRAYSCALE8_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
register GLuint i;
register GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]);
for (i=0;i<n;i++) {
@@ -3623,7 +3624,7 @@ static void put_mono_values_GRAYSCALE8_ximage( PUT_MONO_VALUES_ARGS )
static void put_mono_values_DITHER_5R6G5B_ximage( PUT_MONO_VALUES_ARGS )
{
const GLubyte *color = (const GLubyte *) value;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP];
register GLuint i;
@@ -3648,7 +3649,7 @@ static void put_row_ci_pixmap( PUT_ROW_ARGS )
{
const GLuint *index = (GLuint *) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3677,7 +3678,7 @@ static void put_row_ci_pixmap( PUT_ROW_ARGS )
static void put_row_ci_ximage( PUT_ROW_ARGS )
{
const GLuint *index = (const GLuint *) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
y = YFLIP(xrb, y);
@@ -3707,7 +3708,7 @@ static void put_values_ci_pixmap( PUT_VALUES_ARGS )
{
const GLuint *index = (const GLuint *) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaDrawable buffer = xrb->drawable;
XMesaGC gc = XMESA_BUFFER(ctx->DrawBuffer)->gc;
@@ -3727,7 +3728,7 @@ static void put_values_ci_pixmap( PUT_VALUES_ARGS )
static void put_values_ci_ximage( PUT_VALUES_ARGS )
{
const GLuint *index = (const GLuint *) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaImage *img = xrb->ximage;
register GLuint i;
for (i=0;i<n;i++) {
@@ -3799,7 +3800,7 @@ get_row_ci(GLcontext *ctx, struct gl_renderbuffer *rb,
{
GLuint *index = (GLuint *) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
GLuint i;
y = YFLIP(xrb, y);
@@ -3856,7 +3857,7 @@ get_row_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
{
GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer);
if (xrb->pixmap) {
@@ -4258,7 +4259,7 @@ get_values_ci(GLcontext *ctx, struct gl_renderbuffer *rb,
{
GLuint *indx = (GLuint *) values;
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
GLuint i;
if (xrb->pixmap) {
for (i=0;i<n;i++) {
@@ -4281,7 +4282,7 @@ get_values_rgba(GLcontext *ctx, struct gl_renderbuffer *rb,
GLuint n, const GLint x[], const GLint y[], void *values)
{
GLubyte (*rgba)[4] = (GLubyte (*)[4]) values;
- struct xmesa_renderbuffer *xrb = (struct xmesa_renderbuffer *) rb;
+ GET_XRB(xrb);
const XMesaContext xmesa = XMESA_CONTEXT(ctx);
XMesaDisplay *dpy = xmesa->xm_visual->display;
XMesaBuffer source = XMESA_BUFFER(ctx->DrawBuffer);
diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c
index 61e8986a9b2..289ce11be62 100644
--- a/src/mesa/drivers/x11/xm_tri.c
+++ b/src/mesa/drivers/x11/xm_tri.c
@@ -45,7 +45,7 @@
#define GET_XRB(XRB) struct xmesa_renderbuffer *XRB = \
- (struct xmesa_renderbuffer *) ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped
+ xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped)
/**********************************************************************/
@@ -53,6 +53,8 @@
/**********************************************************************/
+#if CHAN_BITS == 8
+
/*
* XImage, smooth, depth-buffered, PF_TRUECOLOR triangle.
*/
@@ -1307,8 +1309,10 @@
#include "swrast/s_tritemp.h"
+#endif /* CHAN_BITS == 8 */
-#ifdef DEBUG
+
+#if defined(DEBUG) && CHAN_BITS == 8
extern void _xmesa_print_triangle_func( swrast_tri_func triFunc );
void _xmesa_print_triangle_func( swrast_tri_func triFunc )
{
@@ -1441,19 +1445,24 @@ get_triangle_func(GLcontext *ctx)
triFuncName = NULL;
#endif
+#if CHAN_BITS == 8
+ /* trivial fallback tests */
if ((ctx->DrawBuffer->_ColorDrawBufferMask[0]
& (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT)) == 0)
return (swrast_tri_func) NULL;
- if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
- if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
- if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL;
- if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_tri_func) NULL;
+ if (ctx->RenderMode != GL_RENDER)
+ return (swrast_tri_func) NULL;
+ if (ctx->Polygon.SmoothFlag)
+ return (swrast_tri_func) NULL;
+ if (ctx->Texture._EnabledUnits)
+ return (swrast_tri_func) NULL;
+ if (swrast->_RasterMask & MULTI_DRAW_BIT)
+ return (swrast_tri_func) NULL;
if (ctx->Polygon.CullFlag &&
ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
- return (swrast_tri_func) NULL;
+ return (swrast_tri_func) NULL;
- xrb = (struct xmesa_renderbuffer *)
- ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped;
+ xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]->Wrapped);
if (xrb->ximage) {
if ( ctx->Light.ShadeModel==GL_SMOOTH
@@ -1607,13 +1616,10 @@ get_triangle_func(GLcontext *ctx)
return (swrast_tri_func) NULL;
}
}
-
- return (swrast_tri_func) NULL;
- }
- else {
- /* draw to pixmap */
- return (swrast_tri_func) NULL;
}
+#endif /* CHAN_BITS == 8 */
+
+ return (swrast_tri_func) NULL;
}
diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h
index 9d4e6946090..bcac0557b98 100644
--- a/src/mesa/drivers/x11/xmesaP.h
+++ b/src/mesa/drivers/x11/xmesaP.h
@@ -480,12 +480,14 @@ extern const int xmesa_kernel1[16];
/*
* Return pointer to XMesaContext corresponding to a Mesa GLcontext.
* Since we're using structure containment, it's just a cast!.
+ * XXX should use inlined function for better type safety.
*/
#define XMESA_CONTEXT(MESACTX) ((XMesaContext) (MESACTX))
/*
* Return pointer to XMesaBuffer corresponding to a Mesa GLframebuffer.
* Since we're using structure containment, it's just a cast!.
+ * XXX should use inlined function for better type safety.
*/
#define XMESA_BUFFER(MESABUFF) ((XMesaBuffer) (MESABUFF))
@@ -520,6 +522,16 @@ xmesa_set_renderbuffer_funcs(struct xmesa_renderbuffer *xrb,
enum pixel_format pixelformat, GLint depth);
+/**
+ * Using a function instead of an ordinary cast is safer.
+ */
+static INLINE struct xmesa_renderbuffer *
+xmesa_renderbuffer(struct gl_renderbuffer *rb)
+{
+ return (struct xmesa_renderbuffer *) rb;
+}
+
+
/* Plugged into the software rasterizer. Try to use internal
* swrast-style point, line and triangle functions.
*/