[dx58] begin of d3d8/d3dcore split

Raphaël Junqueira fenix at club-internet.fr
Sat Jun 21 06:31:41 CDT 2003


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,
  first, sorry bout this huge patch (difficult to split our code) ;(

 Changelog:
   - begin of d3dcore split for future d3d9 promote
   - currently only debug, utils, shaders and draw functions code
   - definitions of 3 headers (as dx use to do): gl, types, interface

Regards,
Raphael
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQE+9EIgp7NA3AmQTU4RAps8AJ9henSJRUPC5V7IU9r6QwuxeHvcmgCgklwQ
SYPfBwGhe5yPkj3rZ6WOWHg=
=K9ED
-----END PGP SIGNATURE-----
-------------- next part --------------
diff -u --new-file /tmp/basetexture.c dlls/d3dcore/basetexture.c
--- /tmp/basetexture.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/basetexture.c	2003-06-21 13:13:01.000000000 +0200
@@ -0,0 +1,38 @@
+/*
+ * IDirect3DBaseTexture implementation
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+D3DRESOURCETYPE WINAPI IDirect3DBaseTextureImpl_GetType(IDirect3DBaseTextureImpl* This) {
+    /*TRACE("(%p) : returning %d\n", This, This->ResourceType);*/
+    return This->parent.ResourceType;
+}
diff -u --new-file /tmp/d3dcore_gl.h dlls/d3dcore/d3dcore_gl.h
--- /tmp/d3dcore_gl.h	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/d3dcore_gl.h	2003-06-20 20:38:35.000000000 +0200
@@ -0,0 +1,327 @@
+/*
+ * Direct3D gl definitions
+ *
+ * Copyright 2003 Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_D3DCORE_GL_H
+#define __WINE_D3DCORE_GL_H
+
+#ifndef __WINE_CONFIG_H
+# error You must include config.h to use this header
+#endif
+
+#define XMD_H /* This is to prevent the Xmd.h inclusion bug :-/ */
+#include <GL/gl.h>
+#include <GL/glx.h>
+#ifdef HAVE_GL_GLEXT_H
+# include <GL/glext.h>
+#endif
+#undef  XMD_H
+
+/**********************************
+ * Usefull GL Macros
+ */
+
+#define checkGLcall(A) \
+{ \
+    GLint err = glGetError();   \
+    if (err != GL_NO_ERROR) { \
+       FIXME(">>>>>>>>>>>>>>>>> %x from %s @ %s / %d\n", err, A, __FILE__, __LINE__); \
+    } else { \
+       TRACE("%s call ok %s / %d\n", A, __FILE__, __LINE__); \
+    } \
+}
+#define vcheckGLcall(A) \
+{ \
+    GLint err = glGetError();   \
+    if (err != GL_NO_ERROR) { \
+       FIXME(">>>>>>>>>>>>>>>>> %x from %s @ %s / %d\n", err, A, __FILE__, __LINE__); \
+    } else { \
+       VTRACE(("%s call ok %s / %d\n", A, __FILE__, __LINE__)); \
+    } \
+}
+
+#define GL_LIMITS(ExtName)            (This->direct3d->gl_info.max_##ExtName)
+#define GL_SUPPORT(ExtName)           (TRUE == This->direct3d->gl_info.supported[ExtName])
+#define GL_SUPPORT_DEV(ExtName, dev)  (TRUE == (dev)->direct3d->gl_info.supported[ExtName])
+#define GL_EXTCALL(FuncName)          (This->direct3d->gl_info.FuncName)
+
+
+/**********************************
+ * OpenGL Extensions (EXT and ARB)
+ *  defines and functions pointer
+ */
+
+/* GL_EXT_secondary_color */
+#ifndef GL_EXT_secondary_color
+#define GL_EXT_secondary_color 1
+#define GL_COLOR_SUM_EXT                     0x8458
+#define GL_CURRENT_SECONDARY_COLOR_EXT       0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE_EXT    0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE_EXT    0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE_EXT  0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER_EXT 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_EXT         0x845E
+#endif
+typedef void (APIENTRY * PGLFNGLSECONDARYCOLOR3FEXTPROC) (GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRY * PGLFNGLSECONDARYCOLOR3FVEXTPROC) (const GLfloat *v);
+typedef void (APIENTRY * PGLFNGLSECONDARYCOLOR3UBEXTPROC) (GLubyte red, GLubyte green, GLubyte blue);
+typedef void (APIENTRY * PGLFNGLSECONDARYCOLORPOINTEREXTPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+/* GL_EXT_paletted_texture */
+#ifndef GL_EXT_paletted_texture
+#define GL_EXT_paletted_texture 1
+#define GL_COLOR_INDEX1_EXT               0x80E2
+#define GL_COLOR_INDEX2_EXT               0x80E3
+#define GL_COLOR_INDEX4_EXT               0x80E4
+#define GL_COLOR_INDEX8_EXT               0x80E5
+#define GL_COLOR_INDEX12_EXT              0x80E6
+#define GL_COLOR_INDEX16_EXT              0x80E7
+#define GL_TEXTURE_INDEX_SIZE_EXT         0x80ED
+#endif
+typedef void (APIENTRY * PGLFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+/* GL_EXT_point_parameters */
+#ifndef GL_EXT_point_parameters
+#define GL_EXT_point_parameters 1
+#define GL_POINT_SIZE_MIN_EXT             0x8126
+#define GL_POINT_SIZE_MAX_EXT             0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT  0x8128
+#define GL_DISTANCE_ATTENUATION_EXT       0x8129
+#endif
+typedef void (APIENTRY * PGLFNGLPOINTPARAMETERFEXTPROC) (GLenum pname, GLfloat param);
+typedef void (APIENTRY * PGLFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GLfloat *params);
+#ifndef GL_EXT_texture_env_combine
+#define GL_EXT_texture_env_combine 1
+#define GL_COMBINE_EXT                    0x8570
+#define GL_COMBINE_RGB_EXT                0x8571
+#define GL_COMBINE_ALPHA_EXT              0x8572
+#define GL_RGB_SCALE_EXT                  0x8573
+#define GL_ADD_SIGNED_EXT                 0x8574
+#define GL_INTERPOLATE_EXT                0x8575
+#define GL_SUBTRACT_EXT                   0x84E7
+#define GL_CONSTANT_EXT                   0x8576
+#define GL_PRIMARY_COLOR_EXT              0x8577
+#define GL_PREVIOUS_EXT                   0x8578
+#define GL_SOURCE0_RGB_EXT                0x8580
+#define GL_SOURCE1_RGB_EXT                0x8581
+#define GL_SOURCE2_RGB_EXT                0x8582
+#define GL_SOURCE3_RGB_EXT                0x8583
+#define GL_SOURCE4_RGB_EXT                0x8584
+#define GL_SOURCE5_RGB_EXT                0x8585
+#define GL_SOURCE6_RGB_EXT                0x8586
+#define GL_SOURCE7_RGB_EXT                0x8587
+#define GL_SOURCE0_ALPHA_EXT              0x8588
+#define GL_SOURCE1_ALPHA_EXT              0x8589
+#define GL_SOURCE2_ALPHA_EXT              0x858A
+#define GL_SOURCE3_ALPHA_EXT              0x858B
+#define GL_SOURCE4_ALPHA_EXT              0x858C
+#define GL_SOURCE5_ALPHA_EXT              0x858D
+#define GL_SOURCE6_ALPHA_EXT              0x858E
+#define GL_SOURCE7_ALPHA_EXT              0x858F
+#define GL_OPERAND0_RGB_EXT               0x8590
+#define GL_OPERAND1_RGB_EXT               0x8591
+#define GL_OPERAND2_RGB_EXT               0x8592
+#define GL_OPERAND3_RGB_EXT               0x8593
+#define GL_OPERAND4_RGB_EXT               0x8594
+#define GL_OPERAND5_RGB_EXT               0x8595
+#define GL_OPERAND6_RGB_EXT               0x8596
+#define GL_OPERAND7_RGB_EXT               0x8597
+#define GL_OPERAND0_ALPHA_EXT             0x8598
+#define GL_OPERAND1_ALPHA_EXT             0x8599
+#define GL_OPERAND2_ALPHA_EXT             0x859A
+#define GL_OPERAND3_ALPHA_EXT             0x859B
+#define GL_OPERAND4_ALPHA_EXT             0x859C
+#define GL_OPERAND5_ALPHA_EXT             0x859D
+#define GL_OPERAND6_ALPHA_EXT             0x859E
+#define GL_OPERAND7_ALPHA_EXT             0x859F
+#endif
+/* GL_EXT_texture_env_dot3 */
+#ifndef GL_EXT_texture_env_dot3
+#define GL_EXT_texture_env_dot3 1
+#define GL_DOT3_RGB_EXT			  0x8740
+#define GL_DOT3_RGBA_EXT		  0x8741
+#endif
+
+
+/*******
+ * OpenGL Official Version 
+ *  defines 
+ */
+
+/* GL_VERSION_1_3 */
+#if !defined(GL_DOT3_RGBA)
+# define GL_DOT3_RGBA                     0x8741
+#endif
+#if !defined(GL_SUBTRACT)
+# define GL_SUBTRACT                      0x84E7
+#endif
+
+
+/*********************************
+ * OpenGL GLX Extensions
+ *  defines and functions pointer
+ */
+
+
+
+/*********************************
+ * OpenGL GLX Official Version
+ *  defines and functions pointer
+ */
+
+/* GLX_VERSION_1_3 */
+typedef GLXFBConfig * (APIENTRY * PGLXFNGLXGETFBCONFIGSPROC) (Display *dpy, int screen, int *nelements);
+typedef GLXFBConfig * (APIENTRY * PGLXFNGLXCHOOSEFBCONFIGPROC) (Display *dpy, int screen, const int *attrib_list, int *nelements);
+typedef int           (APIENTRY * PGLXFNGLXGETFBCONFIGATTRIBPROC) (Display *dpy, GLXFBConfig config, int attribute, int *value);
+typedef XVisualInfo * (APIENTRY * PGLXFNGLXGETVISUALFROMFBCONFIGPROC) (Display *dpy, GLXFBConfig config);
+typedef GLXWindow     (APIENTRY * PGLXFNGLXCREATEWINDOWPROC) (Display *dpy, GLXFBConfig config, Window win, const int *attrib_list);
+typedef void          (APIENTRY * PGLXFNGLXDESTROYWINDOWPROC) (Display *dpy, GLXWindow win);
+typedef GLXPixmap     (APIENTRY * PGLXFNGLXCREATEPIXMAPPROC) (Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list);
+typedef void          (APIENTRY * PGLXFNGLXDESTROYPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
+typedef GLXPbuffer    (APIENTRY * PGLXFNGLXCREATEPBUFFERPROC) (Display *dpy, GLXFBConfig config, const int *attrib_list);
+typedef void          (APIENTRY * PGLXFNGLXDESTROYPBUFFERPROC) (Display *dpy, GLXPbuffer pbuf);
+typedef void          (APIENTRY * PGLXFNGLXQUERYDRAWABLEPROC) (Display *dpy, GLXDrawable draw, int attribute, unsigned int *value);
+typedef GLXContext    (APIENTRY * PGLXFNGLXCREATENEWCONTEXTPROC) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
+typedef Bool          (APIENTRY * PGLXFNGLXMAKECONTEXTCURRENTPROC) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
+typedef GLXDrawable   (APIENTRY * PGLXFNGLXGETCURRENTREADDRAWABLEPROC) (void);
+typedef Display *     (APIENTRY * PGLXFNGLXGETCURRENTDISPLAYPROC) (void);
+typedef int           (APIENTRY * PGLXFNGLXQUERYCONTEXTPROC) (Display *dpy, GLXContext ctx, int attribute, int *value);
+typedef void          (APIENTRY * PGLXFNGLXSELECTEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long event_mask);
+typedef void          (APIENTRY * PGLXFNGLXGETSELECTEDEVENTPROC) (Display *dpy, GLXDrawable draw, unsigned long *event_mask);
+
+
+/********************************************
+ * OpenGL Supported Extensions (ARB and EXT)
+ */
+
+typedef enum _GL_SupportedExt {
+  /* ARB */
+  ARB_FRAGMENT_PROGRAM,
+  ARB_MULTISAMPLE,
+  ARB_MULTITEXTURE,
+  ARB_POINT_PARAMETERS,
+  ARB_TEXTURE_COMPRESSION,
+  ARB_TEXTURE_CUBE_MAP,
+  ARB_TEXTURE_ENV_COMBINE,
+  ARB_TEXTURE_ENV_DOT3,
+  ARB_VERTEX_PROGRAM,
+  ARB_VERTEX_BLEND,
+  /* EXT */
+  EXT_FOG_COORD,
+  EXT_PALETTED_TEXTURE,
+  EXT_POINT_PARAMETERS,
+  EXT_SECONDARY_COLOR,
+  EXT_TEXTURE_COMPRESSION_S3TC,
+  EXT_TEXTURE_FILTER_ANISOTROPIC,
+  EXT_TEXTURE_LOD,
+  EXT_TEXTURE_LOD_BIAS,
+  EXT_VERTEX_WEIGHTING,
+  /* NVIDIA */
+  NV_FRAGMENT_PROGRAM,
+  NV_VERTEX_PROGRAM,
+  /* ATI */
+  EXT_VERTEX_SHADER,
+
+  OPENGL_SUPPORTED_EXT_END
+} GL_SupportedExt;
+
+typedef enum _GL_VSVersion {
+  VS_VERSION_NOT_SUPPORTED = 0x0,
+  VS_VERSION_10 = 0x10,
+  VS_VERSION_11 = 0x11,
+  VS_VERSION_20 = 0x20,
+  VS_VERSION_30 = 0x30,
+  /*Force 32-bits*/
+  VS_VERSION_FORCE_DWORD = 0x7FFFFFFF
+} GL_VSVersion;
+
+typedef enum _GL_PSVersion {
+  PS_VERSION_NOT_SUPPORTED = 0x0,
+  PS_VERSION_10 = 0x10,
+  PS_VERSION_11 = 0x11,
+  PS_VERSION_12 = 0x12,
+  PS_VERSION_13 = 0x13,
+  PS_VERSION_14 = 0x14,
+  PS_VERSION_20 = 0x20,
+  PS_VERSION_30 = 0x30,
+  /*Force 32-bits*/
+  PS_VERSION_FORCE_DWORD = 0x7FFFFFFF
+} GL_PSVersion;
+
+
+#define GL_EXT_FUNCS_GEN \
+    /** EXT Extensions **/ \
+    /* GL_EXT_fog_coord */ \
+    /* GL_EXT_paletted_texture */ \
+    USE_GL_FUNC(PGLFNGLCOLORTABLEEXTPROC,            glColorTableEXT); \
+    /* GL_EXT_point_parameters */ \
+    USE_GL_FUNC(PGLFNGLPOINTPARAMETERFEXTPROC,       glPointParameterfEXT); \
+    USE_GL_FUNC(PGLFNGLPOINTPARAMETERFVEXTPROC,      glPointParameterfvEXT); \
+    /* GL_EXT_secondary_color */ \
+    USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3UBEXTPROC,     glSecondaryColor3ubEXT); \
+    USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC,      glSecondaryColor3fEXT); \
+    USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC,     glSecondaryColor3fvEXT); \
+    USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT); \
+
+#define GLX_EXT_FUNCS_GEN \
+    /** GLX_VERSION_1_3 **/ \
+    USE_GL_FUNC(PGLXFNGLXCREATEPBUFFERPROC,          glXCreatePbuffer); \
+    USE_GL_FUNC(PGLXFNGLXDESTROYPBUFFERPROC,         glXDestroyPbuffer); \
+    USE_GL_FUNC(PGLXFNGLXCREATEPIXMAPPROC,           glXCreatePixmap); \
+    USE_GL_FUNC(PGLXFNGLXDESTROYPIXMAPPROC,          glXDestroyPixmap); \
+    USE_GL_FUNC(PGLXFNGLXCREATENEWCONTEXTPROC,       glXCreateNewContext); \
+    USE_GL_FUNC(PGLXFNGLXMAKECONTEXTCURRENTPROC,     glXMakeContextCurrent); \
+    USE_GL_FUNC(PGLXFNGLXCHOOSEFBCONFIGPROC,         glXChooseFBConfig); \
+
+#undef APIENTRY
+#undef CALLBACK
+#undef WINAPI
+
+/* Redefines the constants */
+#define CALLBACK    __stdcall
+#define WINAPI      __stdcall
+#define APIENTRY    WINAPI
+
+
+#define USE_GL_FUNC(type, pfn) type pfn;
+typedef struct _GL_Info {
+  /** 
+   * CAPS Constants 
+   */
+  UINT   max_lights;
+  UINT   max_textures;
+  UINT   max_clipplanes;
+
+  GL_PSVersion ps_arb_version;
+  GL_PSVersion ps_nv_version;
+
+  GL_VSVersion vs_arb_version;
+  GL_VSVersion vs_nv_version;
+  GL_VSVersion vs_ati_version;
+  
+  BOOL supported[30];
+
+  /** OpenGL EXT and ARB functions ptr */
+  GL_EXT_FUNCS_GEN;
+  /** OpenGL GLX functions ptr */
+  GLX_EXT_FUNCS_GEN;
+  /**/
+} GL_Info;
+#undef USE_GL_FUNC
+
+
+#endif  /* __WINE_D3DCORE_GL_H */
diff -u --new-file /tmp/d3dcore_interface.h dlls/d3dcore/d3dcore_interface.h
--- /tmp/d3dcore_interface.h	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/d3dcore_interface.h	2003-06-21 13:14:13.000000000 +0200
@@ -0,0 +1,449 @@
+/*
+ * Direct3D core interface include file
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_D3DCORE_INTERFACE_H
+#define __WINE_D3DCORE_INTERFACE_H
+
+#if !defined( __WINE_CONFIG_H )
+# error You must include config.h to use this header
+#endif
+
+#if !defined( __WINE_D3D8_H ) && !defined( __WINE_D3D9_H )
+# error You must include d3d8.h or d3d9.h header to use this header
+#endif
+
+/*****************************************************************
+ * THIS FILE MUST NOT CONTAIN X11 or MESA DEFINES 
+ * PLEASE USE d3dcore_gl.h INSTEAD
+ */
+#define XMD_H /* This is to prevent the Xmd.h inclusion bug :-/ */
+#include <GL/gl.h>
+#include <GL/glx.h>
+#ifdef HAVE_GL_GLEXT_H
+# include <GL/glext.h>
+#endif
+#undef XMD_H
+
+/*****************************************************************
+ * Some defines
+ */
+
+/* Device caps */
+#define MAX_PALETTES      256
+#define MAX_STREAMS       16
+#define MAX_ACTIVE_LIGHTS 8
+#define MAX_CLIPPLANES    D3DMAXUSERCLIPPLANES
+#define MAX_LEVELS        256
+
+/* Other useful values */
+#define HIGHEST_RENDER_STATE 174
+#define HIGHEST_TEXTURE_STATE 29
+#define HIGHEST_TRANSFORMSTATE 512
+#define D3DSBT_RECORDED 0xfffffffe
+
+#define D3D_VSHADER_MAX_CONSTANTS 96
+#define D3D_PSHADER_MAX_CONSTANTS 32
+
+/*****************************************************************
+ * Some Macros
+ */
+extern void (*wine_tsx11_lock_ptr)(void);
+extern void (*wine_tsx11_unlock_ptr)(void);
+
+/* As GLX relies on X, this is needed */
+extern int num_lock;
+#if 0
+#define ENTER_GL() ++num_lock; TRACE("inc lock to: %d\n", num_lock); wine_tsx11_lock_ptr()
+#define LEAVE_GL() if (num_lock > 2) TRACE("fucking locks: %d\n", num_lock); --num_lock; wine_tsx11_unlock_ptr()
+#else
+#define ENTER_GL() wine_tsx11_lock_ptr()
+#define LEAVE_GL() wine_tsx11_unlock_ptr()
+#endif
+
+/* Per-vertex trace: */
+#if 0 /* NOTE: Must be 0 in cvs */
+# define VTRACE(A) TRACE A
+#else 
+# define VTRACE(A) 
+#endif
+#define TRACE_VECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w);
+#define TRACE_STRIDED(sd,name) TRACE( #name "=(data:%p, stride:%ld, type:%ld)\n", sd->u.s.name.lpData, sd->u.s.name.dwStride, sd->u.s.name.dwType);
+
+
+/*****************************************************************
+ * Some includes
+ */
+
+#include "d3dcore_gl.h"
+#include "d3dcore_types.h"
+
+
+/*****************************************************************
+ * Some defines
+ */
+
+typedef struct IDirect3DBaseTextureImpl IDirect3DBaseTextureImpl;
+typedef struct IDirect3DVolumeTextureImpl IDirect3DVolumeTextureImpl;
+typedef struct IDirect3DImpl IDirect3DImpl;
+typedef struct IDirect3DDeviceImpl IDirect3DDeviceImpl;
+typedef struct IDirect3DTextureImpl IDirect3DTextureImpl;
+typedef struct IDirect3DCubeTextureImpl IDirect3DCubeTextureImpl;
+typedef struct IDirect3DIndexBufferImpl IDirect3DIndexBufferImpl;
+typedef struct IDirect3DSurfaceImpl IDirect3DSurfaceImpl;
+typedef struct IDirect3DSwapChainImpl IDirect3DSwapChainImpl;
+typedef struct IDirect3DResourceImpl IDirect3DResourceImpl;
+typedef struct IDirect3DVolumeImpl IDirect3DVolumeImpl;
+typedef struct IDirect3DVertexBufferImpl IDirect3DVertexBufferImpl;
+typedef struct IDirect3DStateBlockImpl IDirect3DStateBlockImpl;
+typedef struct IDirect3DVertexShaderImpl IDirect3DVertexShaderImpl;
+typedef struct IDirect3DPixelShaderImpl IDirect3DPixelShaderImpl;
+typedef struct IDirect3DVertexShaderDeclarationImpl IDirect3DVertexShaderDeclarationImpl;
+
+
+/*************************************************************
+ * d3dcore interfaces defs
+ */
+
+struct IDirect3DImpl {
+    GL_Info  gl_info;
+};
+
+struct IDirect3DDeviceImpl {
+    IDirect3DImpl               *direct3d;
+
+    IDirect3DSurfaceImpl        *frontBuffer;
+    IDirect3DSurfaceImpl        *backBuffer;
+    IDirect3DSurfaceImpl        *depthStencilBuffer;
+
+    IDirect3DSurfaceImpl        *renderTarget;
+    IDirect3DSurfaceImpl        *stencilBufferTarget;
+
+    D3DPRESENT_PARAMETERS         PresentParms;
+    D3DDEVICE_CREATION_PARAMETERS CreateParms;
+
+    UINT                          adapterNo;
+    D3DDEVTYPE                    devType;
+
+    UINT                          srcBlend;
+    UINT                          dstBlend;
+    UINT                          alphafunc;
+    UINT                          stencilfunc;
+
+    /* State block related */
+    BOOL                          isRecordingState;
+    IDirect3DStateBlockImpl      *StateBlock;
+    IDirect3DStateBlockImpl      *UpdateStateBlock;
+
+    /* Other required values */
+    float                         lightPosn[MAX_ACTIVE_LIGHTS][4];
+    float                         lightDirn[MAX_ACTIVE_LIGHTS][4];
+
+    /* palettes texture management */
+    PALETTEENTRY                  palettes[MAX_PALETTES][256];
+    UINT                          currentPalette;
+
+    /* Optimization */
+    D3DMATRIX                     lastProj;
+    D3DMATRIX                     lastView;
+    D3DMATRIX                     lastWorld0;
+    D3DMATRIX                     lastTexTrans[8];
+
+    /* OpenGL related */
+    GLXContext                    glCtx;
+    XVisualInfo                  *visInfo;
+    Display                      *display;
+    HWND                          win_handle;
+    Window                        win;
+    GLXContext                    render_ctx;
+    Drawable                      drawable;
+
+    /* OpenGL Extension related */
+
+    /* Cursor management */
+    BOOL                          bCursorVisible;
+    UINT                          xHotSpot;
+    UINT                          yHotSpot;
+    UINT                          xScreenSpace;
+    UINT                          yScreenSpace;
+    GLint                         cursor;
+
+    UINT                          dummyTextureName[8];
+};
+
+struct IDirect3DVolumeImpl {
+    IDirect3DDeviceImpl    *Device;
+    D3DRESOURCETYPE         ResourceType;
+
+    IUnknown               *Container;
+    D3DVOLUME_DESC          myDesc;
+    BYTE                   *allocatedMemory;
+    UINT                    textureName;
+    UINT                    bytesPerPixel;
+
+    BOOL                    lockable;
+    BOOL                    locked;
+    D3DBOX                  lockedBox;
+    D3DBOX                  dirtyBox;
+    BOOL                    Dirty;
+};
+
+struct IDirect3DSwapChainImpl {
+    IDirect3DSurfaceImpl   *frontBuffer;
+    IDirect3DSurfaceImpl   *backBuffer;
+    IDirect3DSurfaceImpl   *depthStencilBuffer;
+    D3DPRESENT_PARAMETERS   PresentParms;
+    /* OpenGL/GLX related */
+    GLXContext              swap_ctx;
+    Drawable                swap_drawable;
+};
+
+struct IDirect3DSurfaceImpl {
+    IDirect3DDeviceImpl    *Device;
+    D3DRESOURCETYPE         ResourceType;
+
+    IUnknown               *Container;
+    D3DSURFACE_DESC         myDesc;
+    BYTE                   *allocatedMemory;
+    UINT                    textureName;
+    UINT                    bytesPerPixel;
+
+    BOOL                    lockable;
+    BOOL                    locked;
+    RECT                    lockedRect;
+    RECT                    dirtyRect;
+    BOOL                    Dirty;
+};
+
+struct IDirect3DResourceImpl {
+    IDirect3DDeviceImpl   *Device;
+    D3DRESOURCETYPE        ResourceType;
+};
+
+struct IDirect3DVertexBufferImpl {
+    IDirect3DResourceImpl   parent;
+    BYTE                   *allocatedMemory;
+    D3DVERTEXBUFFER_DESC    currentDesc;
+};
+
+struct IDirect3DIndexBufferImpl {
+    IDirect3DResourceImpl   parent;
+    void                   *allocatedMemory;
+    D3DINDEXBUFFER_DESC     currentDesc;
+};
+
+struct IDirect3DBaseTextureImpl {
+    IDirect3DResourceImpl   parent;
+    BOOL                    Dirty;
+    D3DFORMAT               format;
+    UINT                    levels;
+};
+
+extern D3DRESOURCETYPE WINAPI IDirect3DBaseTextureImpl_GetType(IDirect3DBaseTextureImpl* This);
+
+struct IDirect3DCubeTextureImpl {
+    IDirect3DBaseTextureImpl  parent;
+    UINT                      edgeLength;
+    DWORD                     usage;
+    IDirect3DSurfaceImpl     *surfaces[6][MAX_LEVELS];
+};
+
+struct IDirect3DTextureImpl {
+    IDirect3DBaseTextureImpl parent;
+    UINT                     width;
+    UINT                     height;
+    DWORD                    usage;
+    IDirect3DSurfaceImpl    *surfaces[MAX_LEVELS];
+};
+
+struct IDirect3DVolumeTextureImpl {
+    IDirect3DBaseTextureImpl parent;
+    UINT                     width;
+    UINT                     height;
+    UINT                     depth;
+    DWORD                    usage;
+    IDirect3DVolumeImpl     *volumes[MAX_LEVELS];
+};
+
+struct  IDirect3DStateBlockImpl {
+  /* The device */
+  IDirect3DDeviceImpl*       device;
+
+  D3DSTATEBLOCKTYPE          blockType;
+
+  SAVEDSTATES                Changed;
+  SAVEDSTATES                Set;
+  
+  /* Light Enable */
+  BOOL                       lightEnable[MAX_ACTIVE_LIGHTS];
+  
+  /* ClipPlane */
+  double                     clipplane[MAX_CLIPPLANES][4];
+  
+  /* Stream Source */
+  UINT                       stream_stride[MAX_STREAMS];
+  IDirect3DVertexBufferImpl *stream_source[MAX_STREAMS];
+  BOOL                       streamIsUP;
+
+  /* Indices */
+  IDirect3DIndexBufferImpl*  pIndexData;
+  UINT                       baseVertexIndex;
+  
+  /* Texture */
+  IDirect3DBaseTextureImpl*  textures[8];
+  int                        textureDimensions[8];
+  /* Texture State Stage */
+  DWORD                      texture_state[8][HIGHEST_TEXTURE_STATE];
+  
+  /* RenderState */
+  DWORD                      renderstate[HIGHEST_RENDER_STATE];
+  
+  /* Transform */
+  D3DMATRIX                  transforms[HIGHEST_TRANSFORMSTATE];
+
+#if DIRECT3D_VERSION == 0x0800
+  /* ViewPort */
+  D3DVIEWPORT8               viewport;
+  /* Lights */
+  D3DLIGHT8                  lights[MAX_ACTIVE_LIGHTS];  
+  /* Material */
+  D3DMATERIAL8               material;
+#elif DIRECT3D_VERSION == 0x0900
+  /* ViewPort */
+  D3DVIEWPORT9               viewport;
+  /* Lights */
+  D3DLIGHT9                  lights[MAX_ACTIVE_LIGHTS];  
+  /* Material */
+  D3DMATERIAL9               material;
+#endif  
+  
+  DWORD                      FVF;
+
+  /* Vertex Shader */
+  IDirect3DVertexShaderImpl* VertexShader;
+
+  /* Vertex Shader Declaration */
+  IDirect3DVertexShaderDeclarationImpl* vertexShaderDecl;
+  
+  /* Pixel Shader */
+  IDirect3DPixelShaderImpl*  PixelShader;
+  
+  /* Indexed Vertex Blending */
+  D3DVERTEXBLENDFLAGS        vertex_blend;
+  FLOAT                      tween_factor;
+
+  /* Vertex Shader Constant */
+  D3DSHADERVECTOR            vertexShaderConstant[D3D_VSHADER_MAX_CONSTANTS];
+  /* Pixel Shader Constant */
+  D3DSHADERVECTOR            pixelShaderConstant[D3D_PSHADER_MAX_CONSTANTS];
+};
+
+struct IDirect3DVertexShaderDeclarationImpl {
+  /* The device */
+  IDirect3DDeviceImpl* device;
+
+  /** precomputed fvf if simple declaration */
+  DWORD   fvf[MAX_STREAMS];
+  DWORD   allFVF;
+
+  /** dx8 compatible Declaration fields */
+  DWORD*  pDeclaration8;
+  DWORD   declaration8Length;
+};
+
+struct IDirect3DVertexShaderImpl {
+  /* The device */
+  IDirect3DDeviceImpl* device;
+
+  DWORD* function;
+  UINT functionLength;
+  DWORD usage;
+  DWORD version;
+  /* run time datas */
+  VSHADERDATA* data;
+  VSHADERINPUTDATA input;
+  VSHADEROUTPUTDATA output;
+};
+
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_GetFunction(IDirect3DVertexShaderImpl* This, VOID* pData, UINT* pSizeOfData);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_SetConstantB(IDirect3DVertexShaderImpl* This, UINT StartRegister, CONST BOOL*  pConstantData, UINT BoolCount);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_SetConstantI(IDirect3DVertexShaderImpl* This, UINT StartRegister, CONST INT*   pConstantData, UINT Vector4iCount);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_SetConstantF(IDirect3DVertexShaderImpl* This, UINT StartRegister, CONST FLOAT* pConstantData, UINT Vector4fCount);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_GetConstantB(IDirect3DVertexShaderImpl* This, UINT StartRegister, BOOL*  pConstantData, UINT BoolCount);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_GetConstantI(IDirect3DVertexShaderImpl* This, UINT StartRegister, INT*   pConstantData, UINT Vector4iCount);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_GetConstantF(IDirect3DVertexShaderImpl* This, UINT StartRegister, FLOAT* pConstantData, UINT Vector4fCount);
+/* internal Interfaces */
+extern DWORD   WINAPI IDirect3DVertexShaderImpl_GetVersion(IDirect3DVertexShaderImpl* This);
+extern HRESULT WINAPI IDirect3DVertexShaderImpl_ExecuteSW(IDirect3DVertexShaderImpl* This, VSHADERINPUTDATA* input, VSHADEROUTPUTDATA* output);
+extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDeviceImpl* This, IDirect3DVertexShaderImpl* vshader,  DWORD SkipnStrides);
+
+
+struct IDirect3DPixelShaderImpl { 
+  /* The device */
+  IDirect3DDeviceImpl* device;
+
+  DWORD* function;
+  UINT functionLength;
+  DWORD version;
+  /* run time datas */
+  PSHADERDATA* data;
+  PSHADERINPUTDATA input;
+  PSHADEROUTPUTDATA output;
+};
+
+void   IDirect3DDeviceImpl_DrawPrimitive(IDirect3DDeviceImpl* This, int PrimitiveType, long NumPrimitives, long  StartVertexIndex, 
+					 long StartIdx, short idxBytes, const void* idxData, int minIndex);
+void   IDirect3DDeviceImpl_SetTexOp(IDirect3DDeviceImpl* This, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3);
+
+
+void   GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand);
+
+SHORT  D3DFmtGetBpp(IDirect3DDeviceImpl* This, D3DFORMAT fmt);
+GLint  D3DFmt2GLIntFmt(IDirect3DDeviceImpl* This, D3DFORMAT fmt);
+GLenum D3DFmt2GLFmt(IDirect3DDeviceImpl* This, D3DFORMAT fmt);
+GLenum D3DFmt2GLType(IDirect3DDeviceImpl* This, D3DFORMAT fmt);
+
+GLenum D3DFmt2GLDepthFmt(D3DFORMAT fmt);
+GLenum D3DFmt2GLDepthType(D3DFORMAT fmt);
+
+int D3DPrimitiveListGetVertexSize(D3DPRIMITIVETYPE PrimitiveType, int iNumPrim);
+int D3DPrimitive2GLenum(D3DPRIMITIVETYPE PrimitiveType);
+int D3DFVFGetSize(D3DFORMAT fvf);
+
+int SOURCEx_RGB_EXT(DWORD arg);
+int OPERANDx_RGB_EXT(DWORD arg);
+int SOURCEx_ALPHA_EXT(DWORD arg);
+int OPERANDx_ALPHA_EXT(DWORD arg);
+GLenum StencilOp(DWORD op);
+
+
+/**
+ * Debug functions
+ */
+const char* debug_d3ddevicetype(D3DDEVTYPE devtype);
+const char* debug_d3dusage(DWORD usage);
+const char* debug_d3dformat(D3DFORMAT fmt);
+const char* debug_d3dressourcetype(D3DRESOURCETYPE res);
+const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType);
+const char* debug_d3dpool(D3DPOOL Pool);
+const char *debug_d3drenderstate(DWORD State);
+const char *debug_d3dtexturestate(DWORD State);
+
+#endif
diff -u --new-file /tmp/d3dcore_main.c dlls/d3dcore/d3dcore_main.c
--- /tmp/d3dcore_main.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/d3dcore_main.c	2003-06-20 20:42:50.000000000 +0200
@@ -0,0 +1,51 @@
+/* Direct3D 8
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "wine/debug.h"
+
+#include "d3d8.h"
+#include "d3dcore_gl.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+int num_lock = 0;
+void (*wine_tsx11_lock_ptr)(void) = NULL;
+void (*wine_tsx11_unlock_ptr)(void) = NULL;
+
+/* At process attach */
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
+{
+    TRACE("fdwReason=%ld\n", fdwReason);
+       if (fdwReason == DLL_PROCESS_ATTACH)
+       {
+           HMODULE mod = GetModuleHandleA( "x11drv.dll" );
+           if (mod)
+           {
+               wine_tsx11_lock_ptr   = (void *)GetProcAddress( mod, "wine_tsx11_lock" );
+               wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" );
+           }
+       }
+    return TRUE;
+}
diff -u --new-file /tmp/d3dcore.spec dlls/d3dcore/d3dcore.spec
--- /tmp/d3dcore.spec	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/d3dcore.spec	2003-06-20 20:47:34.000000000 +0200
@@ -0,0 +1,2 @@
+@ stdcall ValidatePixelShader(ptr ptr)
+@ stdcall ValidateVertexShader(ptr ptr)
diff -u --new-file /tmp/d3dcore_types.h dlls/d3dcore/d3dcore_types.h
--- /tmp/d3dcore_types.h	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/d3dcore_types.h	2003-06-20 20:38:40.000000000 +0200
@@ -0,0 +1,151 @@
+/*
+ * Direct3D core types include file
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_D3DCORE_TYPES_H
+#define __WINE_D3DCORE_TYPES_H
+
+typedef struct _D3DVECTOR_3 {
+    float x;
+    float y;
+    float z;
+} D3DVECTOR_3;
+
+typedef struct _D3DVECTOR_4 {
+    float x;
+    float y;
+    float z;
+    float w;
+} D3DVECTOR_4;
+
+typedef struct D3DSHADERVECTOR {
+  float x;
+  float y;
+  float z;
+  float w;
+} D3DSHADERVECTOR;
+
+typedef struct D3DSHADERSCALAR {
+  float x;
+} D3DSHADERSCALAR;
+
+typedef D3DSHADERVECTOR VSHADERCONSTANTS8[D3D_VSHADER_MAX_CONSTANTS];
+
+typedef struct VSHADERDATA {
+  /** Run Time Shader Function Constants */
+  /*D3DXBUFFER* constants;*/
+  VSHADERCONSTANTS8 C;
+  /** Shader Code as char ... */
+  CONST DWORD* code;
+  UINT codeLength;
+} VSHADERDATA;
+
+/** temporary here waiting for buffer code */
+typedef struct VSHADERINPUTDATA {
+  D3DSHADERVECTOR V[17];
+} VSHADERINPUTDATA;
+
+/** temporary here waiting for buffer code */
+typedef struct VSHADEROUTPUTDATA {
+  D3DSHADERVECTOR oPos;
+  D3DSHADERVECTOR oD[2];
+  D3DSHADERVECTOR oT[8];
+  D3DSHADERVECTOR oFog;
+  D3DSHADERVECTOR oPts;
+} VSHADEROUTPUTDATA;
+
+typedef D3DSHADERVECTOR PSHADERCONSTANTS8[D3D_PSHADER_MAX_CONSTANTS];
+
+typedef struct PSHADERDATA {
+  /** Run Time Shader Function Constants */
+  /*D3DXBUFFER* constants;*/
+  PSHADERCONSTANTS8 C;
+  /** Shader Code as char ... */
+  CONST DWORD* code;
+  UINT codeLength;
+} PSHADERDATA;
+
+/** temporary here waiting for buffer code */
+typedef struct PSHADERINPUTDATA {
+  D3DSHADERVECTOR V[2];
+  D3DSHADERVECTOR T[8];
+  D3DSHADERVECTOR S[16];
+  /*D3DSHADERVECTOR R[12];*/
+} PSHADERINPUTDATA;
+
+/** temporary here waiting for buffer code */
+typedef struct PSHADEROUTPUTDATA {
+  D3DSHADERVECTOR oC[4];
+  D3DSHADERVECTOR oDepth;
+} PSHADEROUTPUTDATA;
+
+/**
+ * State Block for Begin/End/Capture/Create/Apply State Block
+ *  Note: Very long winded but I do not believe gl Lists will 
+ *  resolve everything we need, so doing it manually for now
+ */
+typedef struct SAVEDSTATES {
+  BOOL          lightEnable[MAX_ACTIVE_LIGHTS];
+  BOOL          Indices;
+  BOOL          lights[MAX_ACTIVE_LIGHTS];
+  BOOL          material;
+  BOOL          stream_source[MAX_STREAMS];
+  BOOL          textures[8];
+  BOOL          transform[HIGHEST_TRANSFORMSTATE];
+  BOOL          viewport;
+  BOOL          vertexShader;
+  BOOL          vertexShaderConstant;
+  BOOL          vertexShaderDecl;
+  BOOL          pixelShader;
+  BOOL          pixelShaderConstant;
+  BOOL          renderstate[HIGHEST_RENDER_STATE];
+  BOOL          texture_state[8][HIGHEST_TEXTURE_STATE];
+  BOOL          clipplane[MAX_CLIPPLANES];
+} SAVEDSTATES;
+
+
+/*****************************************
+ * Structures required to draw primitives 
+ */
+
+typedef struct Direct3DStridedData {
+    BYTE     *lpData;        /* Pointer to start of data               */
+    DWORD     dwStride;      /* Stride between occurances of this data */
+    DWORD     dwType;        /* Type (as in D3DVSDT_TYPE)              */
+} Direct3DStridedData;
+
+typedef struct Direct3DVertexStridedData {
+    union {
+        struct {
+             Direct3DStridedData  position;
+             Direct3DStridedData  blendWeights;
+             Direct3DStridedData  blendMatrixIndices;
+             Direct3DStridedData  normal;
+             Direct3DStridedData  pSize;
+             Direct3DStridedData  diffuse;
+             Direct3DStridedData  specular;
+             Direct3DStridedData  texCoords[8];
+        } DUMMYSTRUCTNAME;
+        Direct3DStridedData input[16];  /* Indexed by constants in D3DVSDE_REGISTER */
+    } DUMMYUNIONNAME;
+} Direct3DVertexStridedData;
+
+
+#endif
diff -u --new-file /tmp/debug.c dlls/d3dcore/debug.c
--- /tmp/debug.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/debug.c	2003-06-20 20:13:52.000000000 +0200
@@ -0,0 +1,295 @@
+/*
+ * D3D core debug utils
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+const char* debug_d3ddevicetype(D3DDEVTYPE devtype) {
+  switch (devtype) {
+#define DEVTYPE_TO_STR(dev) case dev: return #dev
+    DEVTYPE_TO_STR(D3DDEVTYPE_HAL);
+    DEVTYPE_TO_STR(D3DDEVTYPE_REF);
+    DEVTYPE_TO_STR(D3DDEVTYPE_SW);    
+#undef DEVTYPE_TO_STR
+  default:
+    FIXME("Unrecognized %u D3DDEVTYPE!\n", devtype);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dusage(DWORD usage) {
+  switch (usage) {
+#define D3DUSAGE_TO_STR(u) case u: return #u
+    D3DUSAGE_TO_STR(D3DUSAGE_RENDERTARGET);
+    D3DUSAGE_TO_STR(D3DUSAGE_DEPTHSTENCIL);
+    D3DUSAGE_TO_STR(D3DUSAGE_WRITEONLY);
+    D3DUSAGE_TO_STR(D3DUSAGE_SOFTWAREPROCESSING);
+    D3DUSAGE_TO_STR(D3DUSAGE_DONOTCLIP);
+    D3DUSAGE_TO_STR(D3DUSAGE_POINTS);
+    D3DUSAGE_TO_STR(D3DUSAGE_RTPATCHES);
+    D3DUSAGE_TO_STR(D3DUSAGE_NPATCHES);
+    D3DUSAGE_TO_STR(D3DUSAGE_DYNAMIC);
+#undef D3DUSAGE_TO_STR
+  case 0: return "none";
+  default:
+    FIXME("Unrecognized %lu Usage!\n", usage);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dformat(D3DFORMAT fmt) {
+  switch (fmt) {
+#define FMT_TO_STR(fmt) case fmt: return #fmt
+    FMT_TO_STR(D3DFMT_UNKNOWN);
+    FMT_TO_STR(D3DFMT_R8G8B8);
+    FMT_TO_STR(D3DFMT_A8R8G8B8);
+    FMT_TO_STR(D3DFMT_X8R8G8B8);
+    FMT_TO_STR(D3DFMT_R5G6B5);
+    FMT_TO_STR(D3DFMT_X1R5G5B5);
+    FMT_TO_STR(D3DFMT_A1R5G5B5);
+    FMT_TO_STR(D3DFMT_A4R4G4B4);
+    FMT_TO_STR(D3DFMT_R3G3B2);
+    FMT_TO_STR(D3DFMT_A8);
+    FMT_TO_STR(D3DFMT_A8R3G3B2);
+    FMT_TO_STR(D3DFMT_X4R4G4B4);
+    FMT_TO_STR(D3DFMT_A8P8);
+    FMT_TO_STR(D3DFMT_P8);
+    FMT_TO_STR(D3DFMT_L8);
+    FMT_TO_STR(D3DFMT_A8L8);
+    FMT_TO_STR(D3DFMT_A4L4);
+    FMT_TO_STR(D3DFMT_V8U8);
+    FMT_TO_STR(D3DFMT_L6V5U5);
+    FMT_TO_STR(D3DFMT_X8L8V8U8);
+    FMT_TO_STR(D3DFMT_Q8W8V8U8);
+    FMT_TO_STR(D3DFMT_V16U16);
+    FMT_TO_STR(D3DFMT_W11V11U10);
+    FMT_TO_STR(D3DFMT_UYVY);
+    FMT_TO_STR(D3DFMT_YUY2);
+    FMT_TO_STR(D3DFMT_DXT1);
+    FMT_TO_STR(D3DFMT_DXT2);
+    FMT_TO_STR(D3DFMT_DXT3);
+    FMT_TO_STR(D3DFMT_DXT4);
+    FMT_TO_STR(D3DFMT_DXT5);
+    FMT_TO_STR(D3DFMT_D16_LOCKABLE);
+    FMT_TO_STR(D3DFMT_D32);
+    FMT_TO_STR(D3DFMT_D15S1);
+    FMT_TO_STR(D3DFMT_D24S8);
+    FMT_TO_STR(D3DFMT_D16);
+    FMT_TO_STR(D3DFMT_D24X8);
+    FMT_TO_STR(D3DFMT_D24X4S4);
+    FMT_TO_STR(D3DFMT_VERTEXDATA);
+    FMT_TO_STR(D3DFMT_INDEX16);
+    FMT_TO_STR(D3DFMT_INDEX32);
+#undef FMT_TO_STR
+  default:
+    FIXME("Unrecognized %u D3DFORMAT!\n", fmt);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dressourcetype(D3DRESOURCETYPE res) {
+  switch (res) {
+#define RES_TO_STR(res) case res: return #res;
+    RES_TO_STR(D3DRTYPE_SURFACE);
+    RES_TO_STR(D3DRTYPE_VOLUME);
+    RES_TO_STR(D3DRTYPE_TEXTURE);
+    RES_TO_STR(D3DRTYPE_VOLUMETEXTURE);
+    RES_TO_STR(D3DRTYPE_CUBETEXTURE);
+    RES_TO_STR(D3DRTYPE_VERTEXBUFFER);
+    RES_TO_STR(D3DRTYPE_INDEXBUFFER);
+#undef  RES_TO_STR
+  default:
+    FIXME("Unrecognized %u D3DRESOURCETYPE!\n", res);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dprimitivetype(D3DPRIMITIVETYPE PrimitiveType) {
+  switch (PrimitiveType) {
+#define PRIM_TO_STR(prim) case prim: return #prim;
+    PRIM_TO_STR(D3DPT_POINTLIST);
+    PRIM_TO_STR(D3DPT_LINELIST);
+    PRIM_TO_STR(D3DPT_LINESTRIP);
+    PRIM_TO_STR(D3DPT_TRIANGLELIST);
+    PRIM_TO_STR(D3DPT_TRIANGLESTRIP);
+    PRIM_TO_STR(D3DPT_TRIANGLEFAN);
+#undef  PRIM_TO_STR
+  default:
+    FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dpool(D3DPOOL Pool) {
+  switch (Pool) {
+#define POOL_TO_STR(p) case p: return #p;
+    POOL_TO_STR(D3DPOOL_DEFAULT);
+    POOL_TO_STR(D3DPOOL_MANAGED);
+    POOL_TO_STR(D3DPOOL_SYSTEMMEM);
+    POOL_TO_STR(D3DPOOL_SCRATCH);
+#undef  POOL_TO_STR
+  default:
+    FIXME("Unrecognized %u D3DPOOL!\n", Pool);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3drenderstate(DWORD state) {
+  switch (state) {
+#define D3DSTATE_TO_STR(u) case u: return #u
+    D3DSTATE_TO_STR(D3DRS_ZENABLE                   );
+    D3DSTATE_TO_STR(D3DRS_FILLMODE                  );
+    D3DSTATE_TO_STR(D3DRS_SHADEMODE                 );
+    D3DSTATE_TO_STR(D3DRS_LINEPATTERN               );
+    D3DSTATE_TO_STR(D3DRS_ZWRITEENABLE              );
+    D3DSTATE_TO_STR(D3DRS_ALPHATESTENABLE           );
+    D3DSTATE_TO_STR(D3DRS_LASTPIXEL                 );
+    D3DSTATE_TO_STR(D3DRS_SRCBLEND                  );
+    D3DSTATE_TO_STR(D3DRS_DESTBLEND                 );
+    D3DSTATE_TO_STR(D3DRS_CULLMODE                  );
+    D3DSTATE_TO_STR(D3DRS_ZFUNC                     );
+    D3DSTATE_TO_STR(D3DRS_ALPHAREF                  );
+    D3DSTATE_TO_STR(D3DRS_ALPHAFUNC                 );
+    D3DSTATE_TO_STR(D3DRS_DITHERENABLE              );
+    D3DSTATE_TO_STR(D3DRS_ALPHABLENDENABLE          );
+    D3DSTATE_TO_STR(D3DRS_FOGENABLE                 );
+    D3DSTATE_TO_STR(D3DRS_SPECULARENABLE            );
+    D3DSTATE_TO_STR(D3DRS_ZVISIBLE                  );
+    D3DSTATE_TO_STR(D3DRS_FOGCOLOR                  );
+    D3DSTATE_TO_STR(D3DRS_FOGTABLEMODE              );
+    D3DSTATE_TO_STR(D3DRS_FOGSTART                  );
+    D3DSTATE_TO_STR(D3DRS_FOGEND                    );
+    D3DSTATE_TO_STR(D3DRS_FOGDENSITY                );
+    D3DSTATE_TO_STR(D3DRS_EDGEANTIALIAS             );
+    D3DSTATE_TO_STR(D3DRS_ZBIAS                     );
+    D3DSTATE_TO_STR(D3DRS_RANGEFOGENABLE            );
+    D3DSTATE_TO_STR(D3DRS_STENCILENABLE             );
+    D3DSTATE_TO_STR(D3DRS_STENCILFAIL               );
+    D3DSTATE_TO_STR(D3DRS_STENCILZFAIL              );
+    D3DSTATE_TO_STR(D3DRS_STENCILPASS               );
+    D3DSTATE_TO_STR(D3DRS_STENCILFUNC               );
+    D3DSTATE_TO_STR(D3DRS_STENCILREF                );
+    D3DSTATE_TO_STR(D3DRS_STENCILMASK               );
+    D3DSTATE_TO_STR(D3DRS_STENCILWRITEMASK          );
+    D3DSTATE_TO_STR(D3DRS_TEXTUREFACTOR             );
+    D3DSTATE_TO_STR(D3DRS_WRAP0                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP1                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP2                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP3                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP4                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP5                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP6                     );
+    D3DSTATE_TO_STR(D3DRS_WRAP7                     );
+    D3DSTATE_TO_STR(D3DRS_CLIPPING                  );
+    D3DSTATE_TO_STR(D3DRS_LIGHTING                  );
+    D3DSTATE_TO_STR(D3DRS_AMBIENT                   );
+    D3DSTATE_TO_STR(D3DRS_FOGVERTEXMODE             );
+    D3DSTATE_TO_STR(D3DRS_COLORVERTEX               );
+    D3DSTATE_TO_STR(D3DRS_LOCALVIEWER               );
+    D3DSTATE_TO_STR(D3DRS_NORMALIZENORMALS          );
+    D3DSTATE_TO_STR(D3DRS_DIFFUSEMATERIALSOURCE     );
+    D3DSTATE_TO_STR(D3DRS_SPECULARMATERIALSOURCE    );
+    D3DSTATE_TO_STR(D3DRS_AMBIENTMATERIALSOURCE     );
+    D3DSTATE_TO_STR(D3DRS_EMISSIVEMATERIALSOURCE    );
+    D3DSTATE_TO_STR(D3DRS_VERTEXBLEND               );
+    D3DSTATE_TO_STR(D3DRS_CLIPPLANEENABLE           );
+    D3DSTATE_TO_STR(D3DRS_SOFTWAREVERTEXPROCESSING  );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE                 );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE_MIN             );
+    D3DSTATE_TO_STR(D3DRS_POINTSPRITEENABLE         );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALEENABLE          );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_A              );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_B              );
+    D3DSTATE_TO_STR(D3DRS_POINTSCALE_C              );
+    D3DSTATE_TO_STR(D3DRS_MULTISAMPLEANTIALIAS      );
+    D3DSTATE_TO_STR(D3DRS_MULTISAMPLEMASK           );
+    D3DSTATE_TO_STR(D3DRS_PATCHEDGESTYLE            );
+    D3DSTATE_TO_STR(D3DRS_PATCHSEGMENTS             );
+    D3DSTATE_TO_STR(D3DRS_DEBUGMONITORTOKEN         );
+    D3DSTATE_TO_STR(D3DRS_POINTSIZE_MAX             );
+    D3DSTATE_TO_STR(D3DRS_INDEXEDVERTEXBLENDENABLE  );
+    D3DSTATE_TO_STR(D3DRS_COLORWRITEENABLE          );
+    D3DSTATE_TO_STR(D3DRS_TWEENFACTOR               );
+    D3DSTATE_TO_STR(D3DRS_BLENDOP                   );
+    D3DSTATE_TO_STR(D3DRS_POSITIONORDER             );
+    D3DSTATE_TO_STR(D3DRS_NORMALORDER               );
+#undef D3DSTATE_TO_STR
+  default:
+    FIXME("Unrecognized %lu render state!\n", state);
+    return "unrecognized";
+  }
+}
+
+const char* debug_d3dtexturestate(DWORD state) {
+  switch (state) {
+#define D3DSTATE_TO_STR(u) case u: return #u
+    D3DSTATE_TO_STR(D3DTSS_COLOROP               );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG1             );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG2             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAOP               );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG1             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG2             );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT00          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT01          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT10          );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVMAT11          );
+    D3DSTATE_TO_STR(D3DTSS_TEXCOORDINDEX         );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSU              );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSV              );
+    D3DSTATE_TO_STR(D3DTSS_BORDERCOLOR           );
+    D3DSTATE_TO_STR(D3DTSS_MAGFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MINFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MIPFILTER             );
+    D3DSTATE_TO_STR(D3DTSS_MIPMAPLODBIAS         );
+    D3DSTATE_TO_STR(D3DTSS_MAXMIPLEVEL           );
+    D3DSTATE_TO_STR(D3DTSS_MAXANISOTROPY         );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVLSCALE         );
+    D3DSTATE_TO_STR(D3DTSS_BUMPENVLOFFSET        );
+    D3DSTATE_TO_STR(D3DTSS_TEXTURETRANSFORMFLAGS );
+    D3DSTATE_TO_STR(D3DTSS_ADDRESSW              );
+    D3DSTATE_TO_STR(D3DTSS_COLORARG0             );
+    D3DSTATE_TO_STR(D3DTSS_ALPHAARG0             );
+    D3DSTATE_TO_STR(D3DTSS_RESULTARG             );
+#undef D3DSTATE_TO_STR
+  case 12:
+    /* Note D3DTSS are not consecutive, so skip these */
+    return "unused";
+    break;
+  default:
+    FIXME("Unrecognized %lu texture state!\n", state);
+    return "unrecognized";
+  }
+}
+
Les sous-répertoires /tmp/dinput et dlls/d3dcore/dinput sont identiques.
diff -u --new-file /tmp/drawprim.c dlls/d3dcore/drawprim.c
--- /tmp/drawprim.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/drawprim.c	2003-06-21 13:16:44.000000000 +0200
@@ -0,0 +1,1323 @@
+/*
+ * D3D8 utils
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
+
+
+#undef GL_VERSION_1_4 /* To be fixed, caused by mesa headers */
+
+/* Returns bits for what is expected from the fixed function pipeline, and whether 
+   a vertex shader will be in use. Note the fvf bits returned may be split over
+   multiple streams only if the vertex shader was created, otherwise it all relates
+   to stream 0                                                                      */
+BOOL initializeFVF(IDirect3DDeviceImpl* This, 
+                   DWORD *FVFbits,                 /* What to expect in the FVF across all streams */
+                   BOOL *useVertexShaderFunction)  /* Should we use the vertex shader              */
+{
+
+    /* The first thing to work out is if we are using the fixed function pipeline 
+       which is either SetVertexShader with < VS_HIGHESTFIXEDFXF - in which case this
+       is the FVF, or with a shader which was created with no function - in which
+       case there is an FVF per declared stream. If this occurs, we also maintain
+       an 'OR' of all the FVF's together so we know what to expect across all the     
+       streams                                                                        */
+
+    if (NULL == This->UpdateStateBlock->VertexShader) {
+
+        /* Use this as the FVF */
+        *FVFbits = This->UpdateStateBlock->FVF;
+        *useVertexShaderFunction = FALSE;
+        TRACE("FVF explicitally defined, using fixed function pipeline with FVF=%lx\n", *FVFbits);
+
+    } else {
+
+        /* Use created shader */
+        IDirect3DVertexShaderImpl* vertex_shader = NULL;
+        vertex_shader = This->UpdateStateBlock->VertexShader;
+
+        if (vertex_shader == NULL) {
+
+            /* Hmm - User pulled figure out of the air? Unlikely, probably a bug */
+  	    ERR("trying to use an unitialised vertex shader\n");
+            return TRUE;
+
+        } else {
+
+            *FVFbits = This->UpdateStateBlock->vertexShaderDecl->allFVF;
+
+            if (vertex_shader->function == NULL) {
+                /* No function, so many streams supplied plus FVF definition pre stream */
+                *useVertexShaderFunction = FALSE;
+                TRACE("vertex shader (%lx) declared without program, using fixed function pipeline with FVF=%lx\n", This->StateBlock->VertexShader, *FVFbits);
+            } else {
+                /* Vertex shader needs calling */
+                *useVertexShaderFunction = TRUE;
+                TRACE("vertex shader will be used (unusued FVF=%lx)\n", *FVFbits);
+            }
+        }
+    }
+    return FALSE;
+}
+
+/* Issues the glBegin call for gl given the primitive type and count */
+DWORD primitiveToGl(D3DPRIMITIVETYPE PrimitiveType,
+                    DWORD            NumPrimitives,
+                    GLenum          *primType)
+{
+    DWORD   NumVertexes = NumPrimitives;
+
+    switch (PrimitiveType) {
+    case D3DPT_POINTLIST:
+        TRACE("POINTS\n");
+        *primType = GL_POINTS;
+        NumVertexes = NumPrimitives;
+        break;
+
+    case D3DPT_LINELIST:
+        TRACE("LINES\n");
+        *primType = GL_LINES;
+        NumVertexes = NumPrimitives * 2;
+        break;
+
+    case D3DPT_LINESTRIP:
+        TRACE("LINE_STRIP\n");
+        *primType = GL_LINE_STRIP;
+        NumVertexes = NumPrimitives + 1;
+        break;
+
+    case D3DPT_TRIANGLELIST:
+        TRACE("TRIANGLES\n");
+        *primType = GL_TRIANGLES;
+        NumVertexes = NumPrimitives * 3;
+        break;
+
+    case D3DPT_TRIANGLESTRIP:
+        TRACE("TRIANGLE_STRIP\n");
+        *primType = GL_TRIANGLE_STRIP;
+        NumVertexes = NumPrimitives + 2;
+        break;
+
+    case D3DPT_TRIANGLEFAN:
+        TRACE("TRIANGLE_FAN\n");
+        *primType = GL_TRIANGLE_FAN;
+        NumVertexes = NumPrimitives + 2;
+        break;
+
+    default:
+        FIXME("Unhandled primitive\n");
+        *primType    = GL_POINTS;
+        break;
+    }  
+    return NumVertexes;
+}
+
+/* Setup views - Transformed & lit if RHW, else untransformed.
+       Only unlit if Normals are supplied                       
+    Returns: Whether to restore lighting afterwards           */
+BOOL primitiveInitState(IDirect3DDeviceImpl* This, BOOL vtx_transformed, BOOL vtx_lit) {
+
+    BOOL isLightingOn = FALSE;
+
+    /* If no normals, DISABLE lighting otherwise, dont touch lighing as it is 
+       set by the appropriate render state                                    */
+    if (vtx_lit) {
+        isLightingOn = glIsEnabled(GL_LIGHTING);
+        glDisable(GL_LIGHTING);
+        checkGLcall("glDisable(GL_LIGHTING);");
+        TRACE("Enabled lighting as no normals supplied, old state = %d\n", isLightingOn);
+    }
+
+    if (vtx_transformed) {
+        double X, Y, height, width, minZ, maxZ;
+
+        /* Transformed already into viewport coordinates, so we do not need transform
+           matrices. Reset all matrices to identity and leave the default matrix in world 
+           mode.                                                                         */
+        glMatrixMode(GL_MODELVIEW);
+        checkGLcall("glMatrixMode");
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity");
+        /**
+         * As seen in d3d7 code:
+         *  See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
+         *  Correctness Tips section).
+         */
+        glTranslatef(0.375f, 0.375f, 0.0f);
+        checkGLcall("glTranslatef(0.375f, 0.375f, 0.0f)");
+
+        glMatrixMode(GL_PROJECTION);
+        checkGLcall("glMatrixMode");
+        glLoadIdentity();
+        checkGLcall("glLoadIdentity");
+
+        /* Set up the viewport to be full viewport */
+        X      = This->StateBlock->viewport.X;
+        Y      = This->StateBlock->viewport.Y;
+        height = This->StateBlock->viewport.Height;
+        width  = This->StateBlock->viewport.Width;
+        minZ   = This->StateBlock->viewport.MinZ;
+        maxZ   = This->StateBlock->viewport.MaxZ;
+        TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
+        glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
+        checkGLcall("glOrtho");
+
+    } else {
+
+        /* Untransformed, so relies on the view and projection matrices */
+        glMatrixMode(GL_MODELVIEW);
+        checkGLcall("glMatrixMode");
+        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+        glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
+        checkGLcall("glMultMatrixf");
+
+
+        glMatrixMode(GL_PROJECTION);
+        checkGLcall("glMatrixMode");
+        glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
+        checkGLcall("glLoadMatrixf");
+    }
+    return isLightingOn;
+}
+
+void primitiveConvertToStridedData(IDirect3DDeviceImpl* This, Direct3DVertexStridedData *strided, LONG BaseVertexIndex) {
+
+    short         LoopThroughTo = 0;
+    short         nStream;
+    BOOL          canDoViaGLPointers = TRUE;
+    int           numBlends;
+    int           numTextures;
+    int           textureNo;
+    int           coordIdxInfo = 0x00;    /* Information on number of coords supplied */
+    int           numCoords[8];           /* Holding place for D3DFVF_TEXTUREFORMATx  */
+
+    /* OK, Now to setup the data locations 
+       For the non-created vertex shaders, the VertexShader var holds the real 
+          FVF and only stream 0 matters
+       For the created vertex shaders, there is an FVF per stream              */
+    if (NULL != This->UpdateStateBlock->VertexShader) {
+        LoopThroughTo = MAX_STREAMS;
+    } else {
+        LoopThroughTo = 1;
+    }
+
+    /* Work through stream by stream */
+    for (nStream=0; nStream<LoopThroughTo; nStream++) {
+        DWORD  stride  = This->StateBlock->stream_stride[nStream];
+        BYTE  *data    = NULL;
+        DWORD  thisFVF = 0;
+
+        /* Skip empty streams */
+        if (This->StateBlock->stream_source[nStream] == NULL) continue;
+
+        /* Retrieve appropriate FVF */
+        if (LoopThroughTo == 1) { /* VertexShader is FVF */
+            thisFVF = This->UpdateStateBlock->FVF;
+            /* Handle memory passed directly as well as vertex buffers */
+            if (This->StateBlock->streamIsUP == TRUE) {
+                data    = (BYTE*) This->StateBlock->stream_source[nStream];
+            } else {
+                data    = ((IDirect3DVertexBufferImpl*) This->StateBlock->stream_source[nStream])->allocatedMemory;
+            }
+        } else {
+            thisFVF = This->StateBlock->vertexShaderDecl->fvf[nStream];
+            data    = ((IDirect3DVertexBufferImpl*) This->StateBlock->stream_source[nStream])->allocatedMemory;
+        }
+        VTRACE(("FVF for stream %d is %lx\n", nStream, thisFVF));
+        if (thisFVF == 0) continue;
+
+        /* Now convert the stream into pointers */
+
+        /* Shuffle to the beginning of the vertexes to render and index from there */
+        data = data + (BaseVertexIndex * stride);
+
+        /* Either 3 or 4 floats depending on the FVF */
+        /* FIXME: Can blending data be in a different stream to the position data? 
+              and if so using the fixed pipeline how do we handle it               */
+        if (thisFVF & D3DFVF_POSITION_MASK) {
+            strided->u.s.position.lpData    = data;
+            strided->u.s.position.dwType    = D3DVSDT_FLOAT3;
+            strided->u.s.position.dwStride  = stride;
+            data += 3 * sizeof(float);
+            if (thisFVF & D3DFVF_XYZRHW) {
+                strided->u.s.position.dwType = D3DVSDT_FLOAT4;
+                data += sizeof(float);
+            }
+        }
+
+        /* Blending is numBlends * FLOATs followed by a DWORD for UBYTE4 */
+        /** do we have to Check This->UpdateStateBlock->renderstate[D3DRS_INDEXEDVERTEXBLENDENABLE] ? */
+        numBlends = ((thisFVF & D3DFVF_POSITION_MASK) >> 1) - 2 + 
+                    ((FALSE == (thisFVF & D3DFVF_LASTBETA_UBYTE4)) ? 0 : -1);    /* WARNING can be < 0 because -2 */
+        if (numBlends > 0) {
+            canDoViaGLPointers = FALSE; 
+            strided->u.s.blendWeights.lpData    = data;
+            strided->u.s.blendWeights.dwType    = D3DVSDT_FLOAT1 + (numBlends - 1);
+            strided->u.s.blendWeights.dwStride  = stride;
+            data += numBlends * sizeof(FLOAT);
+
+            if (thisFVF & D3DFVF_LASTBETA_UBYTE4) {
+                strided->u.s.blendMatrixIndices.lpData = data;
+                strided->u.s.blendMatrixIndices.dwType  = D3DVSDT_UBYTE4; 
+                strided->u.s.blendMatrixIndices.dwStride= stride; 
+                data += sizeof(DWORD);
+            }
+        }
+
+        /* Normal is always 3 floats */
+        if (thisFVF & D3DFVF_NORMAL) {
+            strided->u.s.normal.lpData    = data;
+            strided->u.s.normal.dwType    = D3DVSDT_FLOAT3;
+            strided->u.s.normal.dwStride  = stride;
+            data += 3 * sizeof(FLOAT);
+        }
+
+        /* Pointsize is a single float */
+        if (thisFVF & D3DFVF_PSIZE) {
+            strided->u.s.pSize.lpData    = data;
+            strided->u.s.pSize.dwType    = D3DVSDT_FLOAT1;
+            strided->u.s.pSize.dwStride  = stride;
+            data += sizeof(FLOAT);
+        }
+
+        /* Diffuse is 4 unsigned bytes */
+        if (thisFVF & D3DFVF_DIFFUSE) {
+            strided->u.s.diffuse.lpData    = data;
+            strided->u.s.diffuse.dwType    = D3DVSDT_SHORT4;
+            strided->u.s.diffuse.dwStride  = stride;
+            data += sizeof(DWORD);
+        }
+
+        /* Specular is 4 unsigned bytes */
+        if (thisFVF & D3DFVF_SPECULAR) {
+            strided->u.s.specular.lpData    = data;
+            strided->u.s.specular.dwType    = D3DVSDT_SHORT4;
+            strided->u.s.specular.dwStride  = stride;
+            data += sizeof(DWORD);
+        }
+
+        /* Texture coords */
+        numTextures   = (thisFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
+        coordIdxInfo  = (thisFVF & 0x00FF0000) >> 16; /* 16 is from definition of D3DFVF_TEXCOORDSIZE1, and is 8 (0-7 stages) * 2bits long */
+
+        /* numTextures indicates the number of texture coordinates supplied */
+        /* However, the first set may not be for stage 0 texture - it all   */
+        /*   depends on D3DTSS_TEXCOORDINDEX.                               */
+        /* The number of bytes for each coordinate set is based off         */
+        /*   D3DFVF_TEXCOORDSIZEn, which are the bottom 2 bits              */
+
+        /* So, for each supplied texture extract the coords */
+        for (textureNo = 0; textureNo < numTextures; ++textureNo) {
+
+            strided->u.s.texCoords[textureNo].lpData    = data;
+            strided->u.s.texCoords[textureNo].dwType    = D3DVSDT_FLOAT1;
+            strided->u.s.texCoords[textureNo].dwStride  = stride;
+            numCoords[textureNo] = coordIdxInfo & 0x03;
+
+            /* Always one set */
+            data += sizeof(float);
+            if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT1) {
+                strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT2;
+                data += sizeof(float);
+                if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT2) {
+                    strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT3;
+                    data += sizeof(float);
+                    if (numCoords[textureNo] != D3DFVF_TEXTUREFORMAT3) {
+                        strided->u.s.texCoords[textureNo].dwType = D3DVSDT_FLOAT4;
+                        data += sizeof(float);
+                    }
+                }
+            }
+            coordIdxInfo = coordIdxInfo >> 2; /* Drop bottom two bits */
+        }
+    }
+}
+
+/* Draw a single vertex using this information */
+void draw_vertex(IDirect3DDeviceImpl* This,                              /* interface    */
+                 BOOL isXYZ,    float x, float y, float z, float rhw,  /* xyzn position*/
+                 BOOL isNormal, float nx, float ny, float nz,          /* normal       */
+                 BOOL isDiffuse, float *dRGBA,                         /* 1st   colors */
+                 BOOL isSpecular, float *sRGB,                         /* 2ndry colors */
+                 BOOL isPtSize, float ptSize,                       /* pointSize    */
+                 D3DVECTOR_4 *texcoords, int *numcoords)               /* texture info */
+{
+    int textureNo;
+    float s, t, r, q;
+
+    /* Diffuse -------------------------------- */
+    if (isDiffuse == TRUE) {
+        glColor4fv(dRGBA);
+        VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", dRGBA[0], dRGBA[1], dRGBA[2], dRGBA[3]));
+    }
+
+    /* Specular Colour ------------------------------------------*/
+    if (isSpecular == TRUE) {
+#if defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+          GL_EXTCALL(glSecondaryColor3fvEXT(sRGB));
+          VTRACE(("glSecondaryColor4f: r,g,b=%f,%f,%f\n", sRGB[0], sRGB[1], sRGB[2]));
+        }
+#endif
+    }
+
+    /* Normal -------------------------------- */
+    if (isNormal == TRUE) {
+        VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
+        glNormal3f(nx, ny, nz);
+    } 
+
+    /* Point Size ----------------------------------------------*/
+    if (isPtSize == TRUE) {
+
+        /* no such functionality in the fixed function GL pipeline */
+        FIXME("Cannot change ptSize here in openGl\n");
+    }
+
+    /* Texture coords --------------------------- */
+    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+            continue ;
+        }
+
+        /* Query tex coords */
+        if (This->StateBlock->textures[textureNo] != NULL) {
+
+            int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+            if (coordIdx > 7) {
+                VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+                continue;
+            } else if (numcoords[coordIdx] == 0) {
+                TRACE("tex: %d - Skipping tex coords, as no data supplied or no coords supplied\n", textureNo);
+                continue;
+            } else {
+
+                /* Initialize vars */
+                s = 0.0f;
+                t = 0.0f;
+                r = 0.0f;
+                q = 0.0f;
+
+                switch (numcoords[coordIdx]) {
+                case 4: q = texcoords[coordIdx].w; /* drop through */
+                case 3: r = texcoords[coordIdx].z; /* drop through */
+                case 2: t = texcoords[coordIdx].y; /* drop through */
+                case 1: s = texcoords[coordIdx].x; 
+                }
+
+                switch (numcoords[coordIdx]) {   /* Supply the provided texture coords */
+                case D3DTTFF_COUNT1:
+                    VTRACE(("tex:%d, s=%f\n", textureNo, s));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
+#else
+                        glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
+#endif
+                    } else {
+                        glTexCoord1f(s);
+                    }
+                    break;
+                case D3DTTFF_COUNT2:
+                    VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
+#else
+                        glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+#endif
+                    } else {
+                        glTexCoord2f(s, t);
+                    }
+                    break;
+                case D3DTTFF_COUNT3:
+                    VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
+#else
+                        glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
+#endif
+                    } else {
+                        glTexCoord3f(s, t, r);
+                    }
+                    break;
+                case D3DTTFF_COUNT4:
+                    VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
+                    if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                        glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
+#else
+                        glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
+#endif
+                    } else {
+                        glTexCoord4f(s, t, r, q);
+                    }
+                    break;
+                default:
+                    FIXME("Should not get here as numCoords should be 0->4 (%x)!\n", numcoords[coordIdx]);
+                }
+            }
+        }
+    } /* End of textures */
+
+    /* Position -------------------------------- */
+    if (isXYZ == TRUE) {
+        if (1.0f == rhw || rhw < 0.01f) {
+            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
+            glVertex3f(x, y, z);
+        } else {
+            GLfloat w = 1.0f / rhw;
+            VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
+            glVertex4f(x * w, y * w, z * w, 1.0f);
+        }
+    }
+}
+
+/* 
+ * Actually draw using the supplied information.
+ * Faster GL version using pointers to data, harder to debug though 
+ * Note does not handle vertex shaders yet                             
+ */
+void drawStridedFast(IDirect3DDeviceImpl* This, Direct3DVertexStridedData *sd, 
+                     int PrimitiveType, ULONG NumPrimitives,
+                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+    int          textureNo   = 0;
+    GLenum       glPrimType  = GL_POINTS;
+    int          NumVertexes = NumPrimitives;
+
+    TRACE("Using fast vertex array code\n");
+
+    /* Vertex Pointers -----------------------------------------*/
+    if (sd->u.s.position.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glVertexPointer(%ld, GL_FLOAT, %ld, %p)\n", 
+                sd->u.s.position.dwStride, 
+                sd->u.s.position.dwType + 1, 
+                sd->u.s.position.lpData));
+        glVertexPointer(sd->u.s.position.dwType + 1, GL_FLOAT, 
+                        sd->u.s.position.dwStride, 
+                        sd->u.s.position.lpData);
+        checkGLcall("glVertexPointer(...)");
+        glEnableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_VERTEX_ARRAY);
+        checkGLcall("glDisableClientState(GL_VERTEX_ARRAY)");
+    }
+
+    /* Blend Data ----------------------------------------------*/
+    if ((sd->u.s.blendWeights.lpData != NULL) || 
+        (sd->u.s.blendMatrixIndices.lpData != NULL)) {
+        /* FIXME: Wont get here as will drop to slow method        */
+        FIXME("Blending not supported in fast draw routine\n");
+
+#if 0 /* Vertex blend support needs to be added */
+        if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
+            /*FIXME("TODO\n");*/
+        } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
+            /*FIXME("TODO\n");*/
+            /*
+            GLExtCall(glVertexWeightPointerEXT)(numBlends, GL_FLOAT, skip, curPos); 
+            checkGLcall("glVertexWeightPointerEXT(numBlends, ...)");
+            glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
+            */
+        } else {
+            FIXME("unsupported blending in openGl\n");
+        }
+    } else {
+        if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
+            FIXME("TODO\n");
+        } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
+            FIXME("TODO\n");
+            /*
+            glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT);
+            checkGLcall("glDisableClientState(GL_VERTEX_WEIGHT_ARRAY_EXT)");
+            */
+        }
+#endif
+    }
+
+    /* Normals -------------------------------------------------*/
+    if (sd->u.s.normal.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glNormalPointer(GL_FLOAT, %ld, %p)\n", 
+                sd->u.s.normal.dwStride, 
+                sd->u.s.normal.lpData));
+        glNormalPointer(GL_FLOAT, 
+                        sd->u.s.normal.dwStride, 
+                        sd->u.s.normal.lpData);
+        checkGLcall("glNormalPointer(...)");
+        glEnableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_NORMAL_ARRAY);
+        checkGLcall("glDisableClientState(GL_NORMAL_ARRAY)");
+        glNormal3f(0, 0, 1);
+        checkGLcall("glNormal3f(0, 0, 1)");
+    }
+
+    /* Point Size ----------------------------------------------*/
+    if (sd->u.s.pSize.lpData != NULL) {
+
+        /* no such functionality in the fixed function GL pipeline */
+        /* FIXME: Wont get here as will drop to slow method        */
+        FIXME("Cannot change ptSize here in openGl\n");
+    }
+
+    /* Diffuse Colour ------------------------------------------*/
+    /*  WARNING: Data here MUST be in RGBA format, so cannot    */
+    /*     go directly into fast mode from app pgm, because     */
+    /*     directx requires data in BGRA format.                */
+    if (sd->u.s.diffuse.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
+                sd->u.s.diffuse.dwStride, 
+                sd->u.s.diffuse.lpData));
+        glColorPointer(4, GL_UNSIGNED_BYTE, 
+                       sd->u.s.diffuse.dwStride, 
+                       sd->u.s.diffuse.lpData);
+        checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        glEnableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
+
+    } else {
+
+        glDisableClientState(GL_COLOR_ARRAY);
+        checkGLcall("glDisableClientState(GL_COLOR_ARRAY)");
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        checkGLcall("glColor4f(1, 1, 1, 1)");
+    }
+
+    /* Specular Colour ------------------------------------------*/
+    if (sd->u.s.specular.lpData != NULL) {
+
+        /* Note dwType == float3 or float4 == 2 or 3 */
+        VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %ld, %p)\n", 
+                sd->u.s.specular.dwStride, 
+                sd->u.s.specular.lpData));
+
+#if defined(GL_VERSION_1_4)
+        glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, 
+                                   sd->u.s.specular.dwStride, 
+                                   sd->u.s.specular.lpData);
+        vcheckGLcall("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, ...)");
+        glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
+        vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY)");
+#elif defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+            GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
+                                                   sd->u.s.specular.dwStride, 
+                                                   sd->u.s.specular.lpData);
+            checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
+            glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+        }
+#else
+        /* Missing specular color is not critical, no warnings */
+        VTRACE(("Specular colour is not supported in this GL implementation\n"));
+#endif
+
+    } else {
+
+#if defined(GL_VERSION_1_4)
+        glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
+        checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY)");
+        glSecondaryColor3f(0, 0, 0);
+        checkGLcall("glSecondaryColor3f(0, 0, 0)");
+#elif defined(GL_EXT_secondary_color)
+        if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+              glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
+            checkGLcall("glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+            GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
+            checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
+        }
+#else
+        /* Do not worry if specular colour missing and disable request */
+#endif
+    }
+
+    /* Texture coords -------------------------------------------*/
+    for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+        if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+            FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+            continue ;
+        }
+
+        /* Query tex coords */
+        if (This->StateBlock->textures[textureNo] != NULL) {
+            int coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+
+            if (coordIdx > 7) {
+                VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+            } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
+                VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n"));
+            } else {
+                int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
+                int numFloats = coordsToUse;
+#if defined(GL_VERSION_1_3)
+                glClientActiveTexture(GL_TEXTURE0 + textureNo);
+#else
+                glClientActiveTextureARB(GL_TEXTURE0_ARB + textureNo);
+#endif
+                /* If texture transform flags in effect, values passed through to vertex
+                   depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
+                if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+
+                    /* This indicates how many coords to use regardless of the
+                       texture type. However, d3d/opengl fill in the rest appropriately */
+                    coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+
+                    /* BUT - Projected is more 'fun' - Cant be done for ptr mode.
+                       Probably should scan enabled texture units and drop back to
+                       slow mode if found? */
+                    if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
+                        FIXME("Cannot handle projected transform state in fast mode\n");
+                    }
+
+                    /* coordsToUse maps to D3DTTFF_COUNT1,2,3,4 == 1,2,3,4 which is correct */
+                }
+                if (numFloats == 0) {
+                    FIXME("Skipping as invalid request - numfloats=%d, coordIdx=%d\n", numFloats, coordIdx);
+                    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+                    checkGLcall("glDisableClientState(GL_TEXTURE_COORD_ARRAY);");
+                } else {
+                    VTRACE(("tex: %d, ptr=%p, numcoords=%d\n", textureNo, sd->u.s.texCoords[coordIdx].lpData, numFloats));
+                    glTexCoordPointer(numFloats, GL_FLOAT, sd->u.s.texCoords[coordIdx].dwStride, sd->u.s.texCoords[coordIdx].lpData);
+                    checkGLcall("glTexCoordPointer(x, ...)");
+                    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+                    checkGLcall("glEnableClientState(GL_TEXTURE_COORD_ARRAY);");
+                }
+            }
+        }
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that 
+       will be                                                              */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Finally do the drawing */
+    if (idxData != NULL) {
+
+        TRACE("glElements(%x, %d, %ld, ...)\n", glPrimType, NumVertexes, minIndex);
+        if (idxSize==2) {
+#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
+            glDrawElements(glPrimType, NumVertexes, GL_UNSIGNED_SHORT,
+                           (char *)idxData+(2 * startIdx));
+#else
+            glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
+                                GL_UNSIGNED_SHORT, (char *)idxData+(2 * startIdx));
+#endif
+        } else {
+#if 1  /* FIXME: Want to use DrawRangeElements, but wrong calculation! */
+            glDrawElements(glPrimType, NumVertexes, GL_UNSIGNED_INT,
+                           (char *)idxData+(4 * startIdx));
+#else
+            glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, 
+                                GL_UNSIGNED_INT, (char *)idxData+(2 * startIdx));
+#endif
+        }
+        checkGLcall("glDrawRangeElements");
+
+    } else {
+
+        /* Note first is now zero as we shuffled along earlier */
+        TRACE("glDrawArrays(%x, 0, %d)\n", glPrimType, NumVertexes);
+        glDrawArrays(glPrimType, 0, NumVertexes);
+        checkGLcall("glDrawArrays");
+
+    }
+}
+
+/* 
+ * Actually draw using the supplied information.
+ * Slower GL version which extracts info about each vertex in turn
+ */
+void drawStridedSlow(IDirect3DDeviceImpl* This, Direct3DVertexStridedData *sd, 
+                     int PrimitiveType, ULONG NumPrimitives,
+                     const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+
+    int                        textureNo    = 0;
+    GLenum                     glPrimType   = GL_POINTS;
+    int                        NumVertexes  = NumPrimitives;
+    const short               *pIdxBufS     = NULL;
+    const long                *pIdxBufL     = NULL;
+    LONG                       SkipnStrides = 0;
+    LONG                       vx_index;
+    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
+    float nx = 0.0f, ny = 0.0, nz = 0.0f;  /* normal x,y,z coordinates   */
+    float rhw = 0.0f;                      /* rhw                        */
+    float ptSize = 0.0f;                   /* Point size                 */
+    DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
+    DWORD specularColor = 0;               /* Specular Color             */
+
+    TRACE("Using slow vertex array code\n");
+
+    /* Variable Initialization */
+    if (idxData != NULL) {
+        if (idxSize == 2) pIdxBufS = (short *) idxData;
+        else pIdxBufL = (long *) idxData;
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that will be */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Start drawing in GL */
+    VTRACE(("glBegin(%x)\n", glPrimType));
+    glBegin(glPrimType);
+
+    /* For each primitive */
+    for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
+
+        /* Initialize diffuse color */
+        diffuseColor = 0xFFFFFFFF;
+
+        /* For indexed data, we need to go a few more strides in */
+        if (idxData != NULL) {
+
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2) {
+                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
+                SkipnStrides = pIdxBufS[startIdx+vx_index];
+            } else {
+                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
+                SkipnStrides = pIdxBufL[startIdx+vx_index];
+            }
+        }
+
+        /* Position Information ------------------ */
+        if (sd->u.s.position.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
+            x = ptrToCoords[0];
+            y = ptrToCoords[1];
+            z = ptrToCoords[2];
+            rhw = 1.0;
+            VTRACE(("x,y,z=%f,%f,%f\n", x,y,z));
+
+            /* RHW follows, only if transformed, ie 4 floats were provided */
+            if (sd->u.s.position.dwType == D3DVSDT_FLOAT4) {
+                rhw = ptrToCoords[3];
+                VTRACE(("rhw=%f\n", rhw));
+            }
+        }
+
+        /* Blending data -------------------------- */
+        if (sd->u.s.blendWeights.lpData != NULL) {
+            /*float *ptrToCoords = (float *)(sd->u.s.blendWeights.lpData + (SkipnStrides * sd->u.s.blendWeights.dwStride));*/
+            FIXME("Blending not supported yet\n");
+
+            if (sd->u.s.blendMatrixIndices.lpData != NULL) {
+                /*DWORD *ptrToCoords = (DWORD *)(sd->u.s.blendMatrixIndices.lpData + (SkipnStrides * sd->u.s.blendMatrixIndices.dwStride));*/
+            }
+        }
+
+        /* Vertex Normal Data (untransformed only)- */
+        if (sd->u.s.normal.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
+            nx = ptrToCoords[0];
+            ny = ptrToCoords[1];
+            nz = ptrToCoords[2];
+            VTRACE(("nx,ny,nz=%f,%f,%f\n", nx, ny, nz));
+        }
+
+        /* Point Size ----------------------------- */
+        if (sd->u.s.pSize.lpData != NULL) {
+
+            float *ptrToCoords = (float *)(sd->u.s.pSize.lpData + (SkipnStrides * sd->u.s.pSize.dwStride));
+            ptSize = ptrToCoords[0];
+            VTRACE(("ptSize=%f\n", ptSize));
+            FIXME("No support for ptSize yet\n");
+        }
+
+        /* Diffuse -------------------------------- */
+        if (sd->u.s.diffuse.lpData != NULL) {
+
+            DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
+            diffuseColor = ptrToCoords[0];
+            VTRACE(("diffuseColor=%lx\n", diffuseColor));
+        }
+
+        /* Specular  -------------------------------- */
+        if (sd->u.s.specular.lpData != NULL) {
+
+            DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
+            specularColor = ptrToCoords[0];
+            VTRACE(("specularColor=%lx\n", specularColor));
+        }
+
+        /* Texture coords --------------------------- */
+        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+
+            if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) {
+                FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
+                continue ;
+            }
+
+            /* Query tex coords */
+            if (This->StateBlock->textures[textureNo] != NULL) {
+
+                int    coordIdx = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXCOORDINDEX];
+                float *ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
+                float  s = 0.0, t = 0.0, r = 0.0, q = 0.0;
+
+                if (coordIdx > 7) {
+                    VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo));
+                    continue;
+                } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
+                    TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
+                    continue;
+                } else {
+
+                    int coordsToUse = sd->u.s.texCoords[coordIdx].dwType + 1; /* 0 == D3DVSDT_FLOAT1 etc */
+
+                    /* If texture transform flags in effect, values passed through to vertex
+                       depend on the D3DTSS_TEXTURETRANSFORMFLAGS */
+                    if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+
+                        /* This indicates how many coords to use regardless of the
+                           texture type. However, d3d/opengl fill in the rest appropriately */
+                        coordsToUse = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+
+                        switch (coordsToUse) {
+                        case 4: q = ptrToCoords[3]; /* drop through */
+                        case 3: r = ptrToCoords[2]; /* drop through */
+                        case 2: t = ptrToCoords[1]; /* drop through */
+                        case 1: s = ptrToCoords[0]; 
+                        }
+
+                        /* BUT - Projected is more 'fun' - Move the last coord to the 'q'
+                           parameter (see comments under D3DTSS_TEXTURETRANSFORMFLAGS */
+                        if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED) {
+                            switch (coordsToUse) {
+                            case 0:  /* Drop Through */
+                            case 1:
+                                FIXME("D3DTTFF_PROJECTED but only zero or one coordinate?\n");
+                                break;
+                            case 2:
+                                q = t;
+                                t = 0.0;
+                                coordsToUse = 4;
+                                break;
+                            case 3:
+                                q = r;
+                                r = 0.0;
+                                coordsToUse = 4;
+                                break;
+                            case 4:  /* Nop here */
+                                break;
+                            default:
+                                FIXME("Unexpected D3DTSS_TEXTURETRANSFORMFLAGS value of %ld\n", 
+                                      This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED);
+                            }
+                        }
+                    } else {
+                        switch (coordsToUse) {
+                        case 4: q = ptrToCoords[3]; /* drop through */
+                        case 3: r = ptrToCoords[2]; /* drop through */
+                        case 2: t = ptrToCoords[1]; /* drop through */
+                        case 1: s = ptrToCoords[0]; 
+                        }
+                    }
+
+                    switch (coordsToUse) {   /* Supply the provided texture coords */
+                    case D3DTTFF_COUNT1:
+                        VTRACE(("tex:%d, s=%f\n", textureNo, s));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord1f(GL_TEXTURE0 + textureNo, s);
+#else
+                            glMultiTexCoord1fARB(GL_TEXTURE0_ARB + textureNo, s);
+#endif
+                        } else {
+                            glTexCoord1f(s);
+                        }
+                        break;
+                    case D3DTTFF_COUNT2:
+                        VTRACE(("tex:%d, s=%f, t=%f\n", textureNo, s, t));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord2f(GL_TEXTURE0 + textureNo, s, t);
+#else
+                            glMultiTexCoord2fARB(GL_TEXTURE0_ARB + textureNo, s, t);
+#endif
+                        } else {
+                            glTexCoord2f(s, t);
+                        }
+                        break;
+                    case D3DTTFF_COUNT3:
+                        VTRACE(("tex:%d, s=%f, t=%f, r=%f\n", textureNo, s, t, r));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord3f(GL_TEXTURE0 + textureNo, s, t, r);
+#else
+                            glMultiTexCoord3fARB(GL_TEXTURE0_ARB + textureNo, s, t, r);
+#endif
+                        } else {
+                            glTexCoord3f(s, t, r);
+                        }
+                        break;
+                    case D3DTTFF_COUNT4:
+                        VTRACE(("tex:%d, s=%f, t=%f, r=%f, q=%f\n", textureNo, s, t, r, q));
+                        if (GL_SUPPORT(ARB_MULTITEXTURE)) {
+#if defined(GL_VERSION_1_3)
+                            glMultiTexCoord4f(GL_TEXTURE0 + textureNo, s, t, r, q);
+#else
+                            glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, s, t, r, q);
+#endif
+                        } else {
+                            glTexCoord4f(s, t, r, q);
+                        }
+                        break;
+                    default:
+                        FIXME("Should not get here as coordsToUse is two bits only (%x)!\n", coordsToUse);
+                    }
+                }
+            }
+        } /* End of textures */
+
+        /* Diffuse -------------------------------- */
+        if (sd->u.s.diffuse.lpData != NULL) {
+            glColor4ub((diffuseColor >> 16) & 0xFF,
+                       (diffuseColor >>  8) & 0xFF,
+                       (diffuseColor >>  0) & 0xFF,
+                       (diffuseColor >> 24) & 0xFF);
+            VTRACE(("glColor4f: r,g,b,a=%f,%f,%f,%f\n", 
+                    ((diffuseColor >> 16) & 0xFF) / 255.0f, 
+                    ((diffuseColor >>  8) & 0xFF) / 255.0f,
+                    ((diffuseColor >>  0) & 0xFF) / 255.0f, 
+                    ((diffuseColor >> 24) & 0xFF) / 255.0f));
+        }
+
+        /* Normal -------------------------------- */
+        if (sd->u.s.normal.lpData != NULL) {
+            VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", nx,ny,nz));
+            glNormal3f(nx, ny, nz);
+        } 
+        
+        /* Position -------------------------------- */
+        if (sd->u.s.position.lpData != NULL) {
+            if (1.0f == rhw || rhw < 0.01f) {
+                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f\n", x,y,z));
+                glVertex3f(x, y, z);
+            } else {
+                VTRACE(("Vertex: glVertex:x,y,z=%f,%f,%f / rhw=%f\n", x,y,z,rhw));
+                glVertex4f(x / rhw, y / rhw, z / rhw, 1.0f / rhw);
+            }
+        }
+
+        /* For non indexed mode, step onto next parts */
+        if (idxData == NULL) {
+            SkipnStrides += 1;
+        }
+    }
+
+    glEnd();
+    checkGLcall("glEnd and previous calls");
+}
+
+/* 
+ * Draw with emulated vertex shaders
+ * Note: strided data is uninitialized, as we need to pass the vertex
+ *     shader directly as ordering irs yet                             
+ */
+void drawStridedSoftwareVS(IDirect3DDeviceImpl* This, Direct3DVertexStridedData *sd, 
+			   int PrimitiveType, ULONG NumPrimitives,
+			   const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) {
+
+    int                        textureNo    = 0;
+    GLenum                     glPrimType   = GL_POINTS;
+    int                        NumVertexes  = NumPrimitives;
+    const short               *pIdxBufS     = NULL;
+    const long                *pIdxBufL     = NULL;
+    LONG                       SkipnStrides = 0;
+    LONG                       vx_index;
+    float x  = 0.0f, y  = 0.0f, z = 0.0f;  /* x,y,z coordinates          */
+    float rhw = 0.0f;                      /* rhw                        */
+    float ptSize = 0.0f;                   /* Point size                 */
+    D3DVECTOR_4 texcoords[8];              /* Texture Coords             */
+    int   numcoords[8];                    /* Number of coords           */
+
+    IDirect3DVertexShaderImpl* vertex_shader = NULL;
+
+    TRACE("Using slow software vertex shader code\n");
+
+    /* Variable Initialization */
+    if (idxData != NULL) {
+        if (idxSize == 2) pIdxBufS = (short *) idxData;
+        else pIdxBufL = (long *) idxData;
+    }
+
+    /* Ok, Work out which primitive is requested and how many vertexes that will be */
+    NumVertexes = primitiveToGl(PrimitiveType, NumPrimitives, &glPrimType);
+
+    /* Retrieve the VS information */
+    vertex_shader = This->StateBlock->VertexShader;
+
+    /* Start drawing in GL */
+    VTRACE(("glBegin(%x)\n", glPrimType));
+    glBegin(glPrimType);
+
+    /* For each primitive */
+    for (vx_index = 0; vx_index < NumVertexes; vx_index++) {
+
+        /* For indexed data, we need to go a few more strides in */
+        if (idxData != NULL) {
+
+            /* Indexed so work out the number of strides to skip */
+            if (idxSize == 2) {
+                VTRACE(("Idx for vertex %ld = %d\n", vx_index, pIdxBufS[startIdx+vx_index]));
+                SkipnStrides = pIdxBufS[startIdx+vx_index];
+            } else {
+                VTRACE(("Idx for vertex %ld = %ld\n", vx_index, pIdxBufL[startIdx+vx_index]));
+                SkipnStrides = pIdxBufL[startIdx+vx_index];
+            }
+        }
+
+        /* Fill the vertex shader input */
+        IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, SkipnStrides);
+
+        /* Now execute the vertex shader */
+        memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA));
+        IDirect3DVertexShaderImpl_ExecuteSW(vertex_shader, &vertex_shader->input, &vertex_shader->output);
+
+        /*
+        TRACE_VECTOR(vertex_shader->output.oPos);
+        TRACE_VECTOR(vertex_shader->output.oD[0]);
+        TRACE_VECTOR(vertex_shader->output.oD[1]);
+        TRACE_VECTOR(vertex_shader->output.oT[0]);
+        TRACE_VECTOR(vertex_shader->output.oT[1]);
+        TRACE_VECTOR(vertex_shader->input.V[0]);
+        TRACE_VECTOR(vertex_shader->data->C[0]);
+        TRACE_VECTOR(vertex_shader->data->C[1]);
+        TRACE_VECTOR(vertex_shader->data->C[2]);
+        TRACE_VECTOR(vertex_shader->data->C[3]);
+        TRACE_VECTOR(vertex_shader->data->C[4]);
+        TRACE_VECTOR(vertex_shader->data->C[5]);
+        TRACE_VECTOR(vertex_shader->data->C[6]);
+        TRACE_VECTOR(vertex_shader->data->C[7]);
+        */
+
+        /* Extract out the output */
+        /*FIXME: Fog coords? */
+        x = vertex_shader->output.oPos.x;
+        y = vertex_shader->output.oPos.y;
+        z = vertex_shader->output.oPos.z;
+        rhw = vertex_shader->output.oPos.w;
+        ptSize = vertex_shader->output.oPts.x; /* Fixme - Is this right? */
+
+        /** Update textures coords using vertex_shader->output.oT[0->7] */
+        memset(texcoords, 0x00, sizeof(texcoords));
+        memset(numcoords, 0x00, sizeof(numcoords));
+        for (textureNo = 0; textureNo < GL_LIMITS(textures); ++textureNo) {
+            if (This->StateBlock->textures[textureNo] != NULL) {
+               texcoords[textureNo].x   = vertex_shader->output.oT[textureNo].x;
+               texcoords[textureNo].y   = vertex_shader->output.oT[textureNo].y;
+               texcoords[textureNo].z   = vertex_shader->output.oT[textureNo].z;
+               texcoords[textureNo].w   = vertex_shader->output.oT[textureNo].w;
+               if (This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE) {
+                   numcoords[textureNo]    = This->UpdateStateBlock->texture_state[textureNo][D3DTSS_TEXTURETRANSFORMFLAGS] & ~D3DTTFF_PROJECTED;
+               } else {
+                   switch (IDirect3DBaseTextureImpl_GetType(This->StateBlock->textures[textureNo])) {
+                   case D3DRTYPE_TEXTURE:       numcoords[textureNo]    = 2; break;
+                   case D3DRTYPE_VOLUMETEXTURE: numcoords[textureNo]    = 3; break;
+                   default:                     numcoords[textureNo]    = 4;
+                   }
+               }
+            } else {
+                numcoords[textureNo]    = 0;
+            }
+        }
+
+        /* Draw using this information */
+        draw_vertex(This,
+                    TRUE, x, y, z, rhw, 
+                    FALSE, 0.0f, 0.0f, 0.0f, 
+                    TRUE, (float*) &vertex_shader->output.oD[0],  
+                    TRUE, (float*) &vertex_shader->output.oD[1],  
+                    FALSE, ptSize,         /* FIXME: Change back when supported */
+                    texcoords, numcoords);
+
+        /* For non indexed mode, step onto next parts */
+        if (idxData == NULL) {
+            SkipnStrides += 1;
+        }
+
+    } /* for each vertex */
+
+    glEnd();
+    checkGLcall("glEnd and previous calls");
+}
+
+/* Routine common to the draw primitive and draw indexed primitive routines */
+void IDirect3DDeviceImpl_DrawPrimitive(IDirect3DDeviceImpl* This,
+				       int PrimitiveType, 
+				       long NumPrimitives,				      
+				       /* for Indexed: */
+				       long  StartVertexIndex,
+				       long  StartIdx,
+				       short idxSize,
+				       const void *idxData,
+				       int   minIndex) {
+
+    BOOL                          rc = FALSE;
+    DWORD                         fvf = 0;
+    IDirect3DVertexShaderImpl    *vertex_shader = NULL;
+    BOOL                          useVertexShaderFunction = FALSE;
+    BOOL                          isLightingOn = FALSE;
+    Direct3DVertexStridedData     dataLocations;
+
+
+    /* Work out what the FVF should look like */
+    rc = initializeFVF(This, &fvf, &useVertexShaderFunction);
+    if (rc) return;
+
+    /* If we will be using a vertex shader, do some initialization for it */
+    if (useVertexShaderFunction == TRUE) {
+        vertex_shader = This->UpdateStateBlock->VertexShader;
+        memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA));
+
+        /** init Constants */
+        if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) {
+            TRACE_(d3d_shader)("vertex shader init Constant\n");
+            IDirect3DVertexShaderImpl_SetConstantF(vertex_shader, 0, (CONST FLOAT*) &This->UpdateStateBlock->vertexShaderConstant[0], 96);
+        }
+    }
+
+    /* Ok, we will be updating the screen from here onwards so grab the lock */
+    ENTER_GL();
+
+    /* Setup transform matrices and sort out */
+    isLightingOn = primitiveInitState(This, 
+                                      fvf & D3DFVF_XYZRHW, 
+                                      !(fvf & D3DFVF_NORMAL));
+
+    /* Initialize all values to null */
+    if (useVertexShaderFunction == FALSE) {
+        memset(&dataLocations, 0x00, sizeof(dataLocations));
+
+        /* Convert to strided data */
+        primitiveConvertToStridedData(This, &dataLocations, StartVertexIndex); 
+
+        /* Dump out what parts we have supplied */
+        TRACE("Strided Data (from FVF/VS): %lx\n", fvf);
+        TRACE_STRIDED((&dataLocations), position);
+        TRACE_STRIDED((&dataLocations), blendWeights);
+        TRACE_STRIDED((&dataLocations), blendMatrixIndices);
+        TRACE_STRIDED((&dataLocations), normal);
+        TRACE_STRIDED((&dataLocations), pSize);
+        TRACE_STRIDED((&dataLocations), diffuse);
+        TRACE_STRIDED((&dataLocations), specular);
+        TRACE_STRIDED((&dataLocations), texCoords[0]);
+        TRACE_STRIDED((&dataLocations), texCoords[1]);
+        TRACE_STRIDED((&dataLocations), texCoords[2]);
+        TRACE_STRIDED((&dataLocations), texCoords[3]);
+        TRACE_STRIDED((&dataLocations), texCoords[4]);
+        TRACE_STRIDED((&dataLocations), texCoords[5]);
+        TRACE_STRIDED((&dataLocations), texCoords[6]);
+        TRACE_STRIDED((&dataLocations), texCoords[7]);
+    }
+
+    /* Now draw the graphics to the screen */
+    if  (useVertexShaderFunction == TRUE) {
+
+        /* Ideally, we should have software FV and hardware VS, possibly
+           depending on the device type?                                 */
+
+        /* We will have to use the very, very slow emulation layer */
+        drawStridedSoftwareVS(This, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx);            
+
+    } else if (TRUE ||
+	       (dataLocations.u.s.pSize.lpData        != NULL) || 
+               (dataLocations.u.s.diffuse.lpData      != NULL) || 
+               (dataLocations.u.s.blendWeights.lpData != NULL)) {
+
+        /* Fixme, Ideally, only use the per-vertex code for software HAL 
+           but until opengl supports all the functions returned to setup 
+           vertex arrays, we need to drop down to the slow mechanism for  
+           certain functions                                              */
+
+        /* We will have to use the slow version of GL per vertex setup */
+        drawStridedSlow(This, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx); 
+
+    } else {
+
+        /* We can use the fast version of GL pointers */
+        drawStridedFast(This, &dataLocations, PrimitiveType, NumPrimitives, 
+                        idxData, idxSize, minIndex, StartIdx);
+    }
+
+    /* If no normals, restore previous lighting state */
+    if (!(fvf & D3DFVF_NORMAL)) {
+        if (isLightingOn) glEnable(GL_LIGHTING);
+        else glDisable(GL_LIGHTING);
+        TRACE("Restored lighting to original state\n");
+    }
+
+    /* Finshed updating the screen, restore lock */
+    LEAVE_GL();
+    TRACE("Done all gl drawing\n");
+
+    /* Diagnostics */
+#if defined(SHOW_FRAME_MAKEUP)
+    {
+        if (isDumpingFrames == TRUE) {
+            D3DLOCKED_RECT r;
+            char buffer[80];
+            IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) This->backBuffer, &r, NULL, D3DLOCK_READONLY);
+            sprintf(buffer, "/tmp/backbuffer_%ld.ppm", primCounter++);
+            TRACE("Saving screenshot %s\n", buffer);
+            IDirect3DSurface8Impl_SaveSnapshot((LPDIRECT3DSURFACE8) This->backBuffer, buffer);
+            IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) This->backBuffer);
+        }
+    }
+#endif
+}
Les sous-répertoires /tmp/.font-unix et dlls/d3dcore/.font-unix sont identiques.
Les sous-répertoires /tmp/gconfd-fenix et dlls/d3dcore/gconfd-fenix sont identiques.
Les sous-répertoires /tmp/gconfd-root et dlls/d3dcore/gconfd-root sont identiques.
Les sous-répertoires /tmp/.ICE-unix et dlls/d3dcore/.ICE-unix sont identiques.
Les sous-répertoires /tmp/kde-fenix et dlls/d3dcore/kde-fenix sont identiques.
Les sous-répertoires /tmp/ksocket-fenix et dlls/d3dcore/ksocket-fenix sont identiques.
diff -u --new-file /tmp/Makefile.in dlls/d3dcore/Makefile.in
--- /tmp/Makefile.in	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/Makefile.in	2003-06-21 13:11:36.000000000 +0200
@@ -0,0 +1,26 @@
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = d3dcore.dll
+IMPORTS   = user32 gdi32 kernel32
+EXTRAINCL = @X_CFLAGS@
+EXTRALIBS = $(LIBUUID) @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@ @OPENGL_LIBS@
+
+LDDLLFLAGS = @LDDLLFLAGS@
+SYMBOLFILE = $(MODULE).tmp.o
+
+C_SRCS = \
+	basetexture.c \
+	d3dcore_main.c \
+	debug.c \
+	drawprim.c \
+	utils.c \
+	vertexshader.c \
+	vertexshaderdeclaration.c
+
+RC_SRCS = version.rc
+
+ at MAKE_DLL_RULES@
+
+### Dependencies:
Les sous-répertoires /tmp/mcop-fenix et dlls/d3dcore/mcop-fenix sont identiques.
diff -u --new-file /tmp/utils.c dlls/d3dcore/utils.c
--- /tmp/utils.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/utils.c	2003-06-20 20:39:28.000000000 +0200
@@ -0,0 +1,1017 @@
+/*
+ * D3D8 utils
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <math.h>
+
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include "d3d8.h"
+#include "d3dcore_gl.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d);
+
+/*
+ * Simple utility routines used for dx -> gl mapping of byte formats
+ */
+int D3DPrimitiveListGetVertexSize(D3DPRIMITIVETYPE PrimitiveType, int iNumPrim) {
+  switch (PrimitiveType) {
+  case D3DPT_POINTLIST:     return iNumPrim;
+  case D3DPT_LINELIST:      return iNumPrim * 2;
+  case D3DPT_LINESTRIP:     return iNumPrim + 1;
+  case D3DPT_TRIANGLELIST:  return iNumPrim * 3;
+  case D3DPT_TRIANGLESTRIP: return iNumPrim + 2;
+  case D3DPT_TRIANGLEFAN:   return iNumPrim + 2;
+  default:
+    FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
+    return 0;
+  }
+}
+
+int D3DPrimitive2GLenum(D3DPRIMITIVETYPE PrimitiveType) {
+  switch (PrimitiveType) {
+  case D3DPT_POINTLIST:     return GL_POINTS;
+  case D3DPT_LINELIST:      return GL_LINES;
+  case D3DPT_LINESTRIP:     return GL_LINE_STRIP;
+  case D3DPT_TRIANGLELIST:  return GL_TRIANGLES;
+  case D3DPT_TRIANGLESTRIP: return GL_TRIANGLE_STRIP;
+  case D3DPT_TRIANGLEFAN:   return GL_TRIANGLE_FAN;
+  default:
+    FIXME("Unrecognized %u D3DPRIMITIVETYPE!\n", PrimitiveType);
+    return GL_POLYGON;
+  }
+}
+
+int D3DFVFGetSize(D3DFORMAT fvf) {
+  int ret = 0;
+  if      (fvf & D3DFVF_XYZ)    ret += 3 * sizeof(float);
+  else if (fvf & D3DFVF_XYZRHW) ret += 4 * sizeof(float);
+  if (fvf & D3DFVF_NORMAL)      ret += 3 * sizeof(float);
+  if (fvf & D3DFVF_PSIZE)       ret += sizeof(float);
+  if (fvf & D3DFVF_DIFFUSE)     ret += sizeof(DWORD);
+  if (fvf & D3DFVF_SPECULAR)    ret += sizeof(DWORD);
+  /*if (fvf & D3DFVF_TEX1)        ret += 1;*/
+  return ret;
+}
+
+GLenum D3DFmt2GLDepthFmt(D3DFORMAT fmt) {
+  switch (fmt) {
+  /* depth/stencil buffer */
+  case D3DFMT_D16_LOCKABLE:
+  case D3DFMT_D16:
+  case D3DFMT_D15S1:
+  case D3DFMT_D24X4S4:
+  case D3DFMT_D24S8:
+  case D3DFMT_D24X8:
+  case D3DFMT_D32:
+    return GL_DEPTH_COMPONENT;
+  default:
+    FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+  }
+  return 0;
+}
+
+GLenum D3DFmt2GLDepthType(D3DFORMAT fmt) {
+  switch (fmt) {
+  /* depth/stencil buffer */
+  case D3DFMT_D15S1:
+  case D3DFMT_D16_LOCKABLE:     
+  case D3DFMT_D16:              
+    return GL_UNSIGNED_SHORT;
+  case D3DFMT_D24X4S4:          
+  case D3DFMT_D24S8:            
+  case D3DFMT_D24X8:            
+  case D3DFMT_D32:              
+    return GL_UNSIGNED_INT;
+  default:
+    FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+  }
+  return 0;
+}
+
+SHORT D3DFmtGetBpp(IDirect3DDeviceImpl* This, D3DFORMAT fmt) {
+    SHORT retVal;
+
+    switch (fmt) {
+    /* color buffer */
+    case D3DFMT_P8:               retVal = 1; break;
+    case D3DFMT_R3G3B2:           retVal = 1; break;
+    case D3DFMT_R5G6B5:           retVal = 2; break;
+    case D3DFMT_X1R5G5B5:         retVal = 2; break;
+    case D3DFMT_A4R4G4B4:         retVal = 2; break;
+    case D3DFMT_X4R4G4B4:         retVal = 2; break;
+    case D3DFMT_A1R5G5B5:         retVal = 2; break;
+    case D3DFMT_R8G8B8:           retVal = 3; break;
+    case D3DFMT_X8R8G8B8:         retVal = 4; break;
+    case D3DFMT_A8R8G8B8:         retVal = 4; break;
+    /* depth/stencil buffer */
+    case D3DFMT_D16_LOCKABLE:     retVal = 2; break;
+    case D3DFMT_D16:              retVal = 2; break;
+    case D3DFMT_D15S1:            retVal = 2; break;
+    case D3DFMT_D24X4S4:          retVal = 4; break;
+    case D3DFMT_D24S8:            retVal = 4; break;
+    case D3DFMT_D24X8:            retVal = 4; break;
+    case D3DFMT_D32:              retVal = 4; break;
+    /* unknown */				  
+    case D3DFMT_UNKNOWN:
+      /* Guess at the highest value of the above */
+      TRACE("D3DFMT_UNKNOWN - Guessing at 4 bytes/pixel %u\n", fmt);
+      retVal = 4;
+      break;
+
+    default:
+      FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+      retVal = 4;
+    }
+    TRACE("bytes/Pxl for fmt(%u,%s) = %d\n", fmt, debug_d3dformat(fmt), retVal);
+    return retVal;
+}
+
+GLint D3DFmt2GLIntFmt(IDirect3DDeviceImpl* This, D3DFORMAT fmt) {
+    GLint retVal;
+
+    switch (fmt) {
+    case D3DFMT_P8:               retVal = GL_COLOR_INDEX8_EXT; break;
+    case D3DFMT_A8P8:             retVal = GL_COLOR_INDEX8_EXT; break;
+
+    case D3DFMT_A4R4G4B4:         retVal = GL_RGBA4; break;
+    case D3DFMT_A8R8G8B8:         retVal = GL_RGBA8; break;
+    case D3DFMT_X8R8G8B8:         retVal = GL_RGB8; break;
+    case D3DFMT_R8G8B8:           retVal = GL_RGB8; break;
+    case D3DFMT_R5G6B5:           retVal = GL_RGB5; break; /* fixme: internal format 6 for g? */
+    case D3DFMT_A1R5G5B5:         retVal = GL_RGB5_A1; break;
+    default:
+        FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+        retVal = GL_RGB8;
+    }
+#if defined(GL_EXT_texture_compression_s3tc)
+    if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
+      switch (fmt) {
+      case D3DFMT_DXT1:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+      case D3DFMT_DXT3:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+      case D3DFMT_DXT5:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+      default:
+	/* stupid compiler */
+	break;
+      }
+    }
+#endif
+    TRACE("fmt2glintFmt for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
+    return retVal;
+}
+
+GLenum D3DFmt2GLFmt(IDirect3DDeviceImpl* This, D3DFORMAT fmt) {
+    GLenum retVal;
+
+    switch (fmt) {
+    case D3DFMT_P8:               retVal = GL_COLOR_INDEX; break;
+    case D3DFMT_A8P8:             retVal = GL_COLOR_INDEX; break;
+
+    case D3DFMT_A4R4G4B4:         retVal = GL_BGRA; break;
+    case D3DFMT_A8R8G8B8:         retVal = GL_BGRA; break;
+    case D3DFMT_X8R8G8B8:         retVal = GL_BGRA; break;
+    case D3DFMT_R8G8B8:           retVal = GL_BGR; break;
+    case D3DFMT_R5G6B5:           retVal = GL_RGB; break;
+    case D3DFMT_A1R5G5B5:         retVal = GL_BGRA; break;
+    default:
+        FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+        retVal = GL_BGR;
+    }
+#if defined(GL_EXT_texture_compression_s3tc)
+    if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
+      switch (fmt) {
+      case D3DFMT_DXT1:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; break;
+      case D3DFMT_DXT3:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; break;
+      case D3DFMT_DXT5:             retVal = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break;
+      default:
+	/* stupid compiler */
+	break;
+      }
+    }
+#endif
+    TRACE("fmt2glFmt for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
+    return retVal;
+}
+
+GLenum D3DFmt2GLType(IDirect3DDeviceImpl* This, D3DFORMAT fmt) {
+    GLenum retVal;
+
+    switch (fmt) {
+    case D3DFMT_P8:               retVal = GL_UNSIGNED_BYTE; break;
+    case D3DFMT_A8P8:             retVal = GL_UNSIGNED_BYTE; break;
+
+    case D3DFMT_A4R4G4B4:         retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break;
+    case D3DFMT_A8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
+    case D3DFMT_X8R8G8B8:         retVal = GL_UNSIGNED_BYTE; break;
+    case D3DFMT_R5G6B5:           retVal = GL_UNSIGNED_SHORT_5_6_5; break;
+    case D3DFMT_R8G8B8:           retVal = GL_UNSIGNED_BYTE; break;
+    case D3DFMT_A1R5G5B5:         retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break;
+    default:
+        FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt));
+        retVal = GL_UNSIGNED_BYTE;
+    }
+#if defined(GL_EXT_texture_compression_s3tc)
+    if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
+      switch (fmt) {
+      case D3DFMT_DXT1:             retVal = 0; break;
+      case D3DFMT_DXT3:             retVal = 0; break;
+      case D3DFMT_DXT5:             retVal = 0; break;
+      default:
+	/* stupid compiler */
+	break;
+      }
+    }
+#endif
+    TRACE("fmt2glType for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal);
+    return retVal;
+}
+
+int SOURCEx_RGB_EXT(DWORD arg) {
+    switch(arg) {
+    case D3DTSS_COLORARG0: return GL_SOURCE2_RGB_EXT;
+    case D3DTSS_COLORARG1: return GL_SOURCE0_RGB_EXT;
+    case D3DTSS_COLORARG2: return GL_SOURCE1_RGB_EXT;
+    case D3DTSS_ALPHAARG0:
+    case D3DTSS_ALPHAARG1:
+    case D3DTSS_ALPHAARG2:
+    default:
+        FIXME("Invalid arg %ld\n", arg);
+        return GL_SOURCE0_RGB_EXT;
+    }
+}
+
+int OPERANDx_RGB_EXT(DWORD arg) {
+    switch(arg) {
+    case D3DTSS_COLORARG0: return GL_OPERAND2_RGB_EXT;
+    case D3DTSS_COLORARG1: return GL_OPERAND0_RGB_EXT;
+    case D3DTSS_COLORARG2: return GL_OPERAND1_RGB_EXT;
+    case D3DTSS_ALPHAARG0:
+    case D3DTSS_ALPHAARG1:
+    case D3DTSS_ALPHAARG2:
+    default:
+        FIXME("Invalid arg %ld\n", arg);
+        return GL_OPERAND0_RGB_EXT;
+    }
+}
+
+int SOURCEx_ALPHA_EXT(DWORD arg) {
+    switch(arg) {
+    case D3DTSS_ALPHAARG0:  return GL_SOURCE2_ALPHA_EXT;
+    case D3DTSS_ALPHAARG1:  return GL_SOURCE0_ALPHA_EXT;
+    case D3DTSS_ALPHAARG2:  return GL_SOURCE1_ALPHA_EXT;
+    case D3DTSS_COLORARG0:
+    case D3DTSS_COLORARG1:
+    case D3DTSS_COLORARG2:
+    default:
+        FIXME("Invalid arg %ld\n", arg);
+        return GL_SOURCE0_ALPHA_EXT;
+    }
+}
+
+int OPERANDx_ALPHA_EXT(DWORD arg) {
+    switch(arg) {
+    case D3DTSS_ALPHAARG0:  return GL_OPERAND2_ALPHA_EXT;
+    case D3DTSS_ALPHAARG1:  return GL_OPERAND0_ALPHA_EXT;
+    case D3DTSS_ALPHAARG2:  return GL_OPERAND1_ALPHA_EXT;
+    case D3DTSS_COLORARG0:
+    case D3DTSS_COLORARG1:
+    case D3DTSS_COLORARG2:
+    default:
+        FIXME("Invalid arg %ld\n", arg);
+        return GL_OPERAND0_ALPHA_EXT;
+    }
+}
+
+GLenum StencilOp(DWORD op) {
+    switch(op) {                
+    case D3DSTENCILOP_KEEP    : return GL_KEEP;
+    case D3DSTENCILOP_ZERO    : return GL_ZERO;
+    case D3DSTENCILOP_REPLACE : return GL_REPLACE;
+    case D3DSTENCILOP_INCRSAT : return GL_INCR;
+    case D3DSTENCILOP_DECRSAT : return GL_DECR;
+    case D3DSTENCILOP_INVERT  : return GL_INVERT; 
+#if defined(GL_VERSION_1_4)
+    case D3DSTENCILOP_INCR    : return GL_INCR_WRAP;
+    case D3DSTENCILOP_DECR    : return GL_DECR_WRAP;
+#elif defined(GL_EXT_stencil_wrap)
+    case D3DSTENCILOP_INCR    : return GL_INCR_WRAP_EXT;
+    case D3DSTENCILOP_DECR    : return GL_DECR_WRAP_EXT;
+#else
+    case D3DSTENCILOP_INCR    : FIXME("Unsupported stencil op D3DSTENCILOP_INCR\n");
+                                return GL_INCR; /* Fixme - needs to support wrap */
+    case D3DSTENCILOP_DECR    : FIXME("Unsupported stencil op D3DSTENCILOP_DECR\n");
+                                return GL_DECR; /* Fixme - needs to support wrap */
+#endif
+    default:
+        FIXME("Invalid stencil op %ld\n", op);
+        return GL_ALWAYS;
+    }
+}
+
+/**
+ * @nodoc: todo
+ */
+void GetSrcAndOpFromValue(DWORD iValue, BOOL isAlphaArg, GLenum* source, GLenum* operand) 
+{
+  BOOL isAlphaReplicate = FALSE;
+  BOOL isComplement     = FALSE;
+  
+  *operand = GL_SRC_COLOR;
+  *source = GL_TEXTURE;
+  
+  /* Catch alpha replicate */
+  if (iValue & D3DTA_ALPHAREPLICATE) {
+    iValue = iValue & ~D3DTA_ALPHAREPLICATE;
+    isAlphaReplicate = TRUE;
+  }
+  
+  /* Catch Complement */
+  if (iValue & D3DTA_COMPLEMENT) {
+    iValue = iValue & ~D3DTA_COMPLEMENT;
+    isComplement = TRUE;
+  }
+  
+  /* Calculate the operand */
+  if (isAlphaReplicate && !isComplement) {
+    *operand = GL_SRC_ALPHA;
+  } else if (isAlphaReplicate && isComplement) {
+    *operand = GL_ONE_MINUS_SRC_ALPHA;
+  } else if (isComplement) {
+    if (isAlphaArg) {
+      *operand = GL_ONE_MINUS_SRC_ALPHA;
+    } else {
+      *operand = GL_ONE_MINUS_SRC_COLOR;
+    }
+  } else {
+    if (isAlphaArg) {
+      *operand = GL_SRC_ALPHA;
+    } else {
+      *operand = GL_SRC_COLOR;
+    }
+  }
+  
+  /* Calculate the source */
+  switch (iValue & D3DTA_SELECTMASK) {
+  case D3DTA_CURRENT:   *source  = GL_PREVIOUS_EXT;
+    break;
+  case D3DTA_DIFFUSE:   *source  = GL_PRIMARY_COLOR_EXT;
+    break;
+  case D3DTA_TEXTURE:   *source  = GL_TEXTURE;
+    break;
+  case D3DTA_TFACTOR:   *source  = GL_CONSTANT_EXT;
+    break;
+  case D3DTA_SPECULAR:
+    /**
+     * According to the GL_ARB_texture_env_combine specs, SPECULAR is 'Secondary color' and
+     * isnt supported until base GL supports it
+     * There is no concept of temp registers as far as I can tell
+     */
+
+  default:
+    FIXME("Unrecognized or unhandled texture arg %ld\n", iValue);
+    *source = GL_TEXTURE;
+  }
+}
+
+/* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
+#if defined (GL_VERSION_1_3)
+# define useext(A) A
+# define combine_ext 1
+#elif defined (GL_EXT_texture_env_combine)
+# define useext(A) A##_EXT
+# define combine_ext 1
+#elif defined (GL_ARB_texture_env_combine)
+# define useext(A) A##_ARB
+# define combine_ext 1
+#else
+# undef combine_ext
+#endif
+
+#if !defined(combine_ext)
+void IDirect3DDeviceImpl_SetTexOp(IDirect3DDeviceImpl* This, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{ 
+        FIXME("Requires opengl combine extensions to work\n");
+        return;
+}
+#else
+/* Setup the texture operations texture stage states */
+void IDirect3DDeviceImpl_SetTexOp(IDirect3DDeviceImpl* This, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
+{
+	GLenum src1, src2, src3;
+	GLenum opr1, opr2, opr3;
+	GLenum comb_target;
+	GLenum src0_target, src1_target, src2_target;
+	GLenum opr0_target, opr1_target, opr2_target;
+	GLenum scal_target;
+	GLenum opr=0, invopr, src3_target, opr3_target;
+        BOOL Handled = FALSE;
+
+        TRACE("Alpha?(%d), Stage:%d Op(%d), a1(%ld), a2(%ld), a3(%ld)\n", isAlpha, Stage, op, arg1, arg2, arg3);
+        if (op == D3DTOP_DISABLE) return;
+
+	ENTER_GL();
+
+        /* Note: Operations usually involve two ars, src0 and src1 and are operations of
+           the form (a1 <operation> a2). However, some of the more complex operations
+           take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added  
+           in a third parameter called a0. Therefore these are operations of the form
+           a0 <operation> a1 <operation> a2, ie the new parameter goes to the front.
+           
+           However, below we treat the new (a0) parameter as src2/opr2, so in the actual
+           functions below, expect their syntax to differ slightly to those listed in the
+           manuals, ie replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
+           This affects D3DTOP_MULTIPLYADD and D3DTOP_LERP                               */
+           
+	if (isAlpha) {
+		comb_target = useext(GL_COMBINE_ALPHA);
+		src0_target = useext(GL_SOURCE0_ALPHA);
+		src1_target = useext(GL_SOURCE1_ALPHA);
+		src2_target = useext(GL_SOURCE2_ALPHA);
+		opr0_target = useext(GL_OPERAND0_ALPHA);
+		opr1_target = useext(GL_OPERAND1_ALPHA);
+		opr2_target = useext(GL_OPERAND2_ALPHA);
+		scal_target = GL_ALPHA_SCALE;
+	}
+	else {
+		comb_target = useext(GL_COMBINE_RGB);
+		src0_target = useext(GL_SOURCE0_RGB);
+		src1_target = useext(GL_SOURCE1_RGB);
+		src2_target = useext(GL_SOURCE2_RGB);
+		opr0_target = useext(GL_OPERAND0_RGB);
+		opr1_target = useext(GL_OPERAND1_RGB);
+		opr2_target = useext(GL_OPERAND2_RGB);
+		scal_target = useext(GL_RGB_SCALE);
+	}
+
+        /* From MSDN (D3DTSS_ALPHAARG1) : 
+           The default argument is D3DTA_TEXTURE. If no texture is set for this stage, 
+                   then the default argument is D3DTA_DIFFUSE.
+                   FIXME? If texture added/removed, may need to reset back as well?    */
+        if (isAlpha && This->StateBlock->textures[Stage] == NULL && arg1 == D3DTA_TEXTURE) {
+            GetSrcAndOpFromValue(D3DTA_DIFFUSE, isAlpha, &src1, &opr1);  
+        } else {
+            GetSrcAndOpFromValue(arg1, isAlpha, &src1, &opr1);
+        }
+        GetSrcAndOpFromValue(arg2, isAlpha, &src2, &opr2);
+        GetSrcAndOpFromValue(arg3, isAlpha, &src3, &opr3);
+        
+        TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
+
+        Handled = TRUE; /* Assume will be handled */
+	switch (op) {
+	case D3DTOP_SELECTARG1:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_SELECTARG2:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATE:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATE2X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+		break;
+	case D3DTOP_MODULATE4X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
+		break;
+	case D3DTOP_ADD:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_ADDSIGNED:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_ADDSIGNED2X:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
+		break;
+        case D3DTOP_SUBTRACT:
+	  if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+	  } else {
+                FIXME("This version of opengl does not support GL_SUBTRACT\n");
+	  }
+	  break;
+
+	case D3DTOP_BLENDDIFFUSEALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDTEXTUREALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDFACTORALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDCURRENTALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
+		checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+        case D3DTOP_DOTPRODUCT3: 
+	       if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
+		  glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA);
+		  checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA");
+		} else {
+		  FIXME("This version of opengl does not support GL_DOT3\n");
+		}
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_LERP:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
+		checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, src3);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	default:
+		Handled = FALSE;
+	}
+
+        if (Handled) {
+            BOOL  combineOK = TRUE;
+#if defined(GL_NV_texture_env_combine4)
+            DWORD op2;
+
+            if (isAlpha) {
+                op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_COLOROP];
+            } else {
+                op2 = This->UpdateStateBlock->texture_state[Stage][D3DTSS_ALPHAOP];
+            }
+
+           /* Note: If COMBINE4 in effect cant go back to combine! */
+           switch (op2)
+           {
+           case D3DTOP_ADDSMOOTH:
+           case D3DTOP_BLENDTEXTUREALPHAPM:
+           case D3DTOP_MODULATEALPHA_ADDCOLOR:
+           case D3DTOP_MODULATECOLOR_ADDALPHA:
+           case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+           case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+           case D3DTOP_MULTIPLYADD:
+               /* Ignore those implemented in both cases */
+               switch (op) {
+               case D3DTOP_SELECTARG1:
+               case D3DTOP_SELECTARG2:
+                   combineOK = FALSE;
+                   Handled   = FALSE;
+                   break;
+               default:
+                   FIXME("Cant have COMBINE4 and COMBINE in efferct together, thisop=%d, otherop=%ld, isAlpha(%d)\n", 
+                              op, op2, isAlpha);
+
+		   LEAVE_GL();
+                   return;
+               }
+           }
+#endif
+
+           if (combineOK == TRUE) {
+	       glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
+	       checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
+
+	       LEAVE_GL();
+	       return;
+           }
+        }
+
+        /* Other texture operations require special extensions: */
+#if defined(GL_NV_texture_env_combine4)
+	if (isAlpha) {
+                opr = GL_SRC_ALPHA;
+		invopr = GL_ONE_MINUS_SRC_ALPHA;
+		src3_target = GL_SOURCE3_ALPHA_NV;
+		opr3_target = GL_OPERAND3_ALPHA_NV;
+	}
+	else {
+                opr = GL_SRC_COLOR;
+		invopr = GL_ONE_MINUS_SRC_COLOR;
+		src3_target = GL_SOURCE3_RGB_NV;
+		opr3_target = GL_OPERAND3_RGB_NV;
+	}
+        Handled = TRUE; /* Again, assume handled */
+	switch (op) {
+        case D3DTOP_SELECTARG1:                                          /* = a1 * 1 + 0 * 0 */
+        case D3DTOP_SELECTARG2:                                          /* = a2 * 1 + 0 * 0 */
+                glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+                if (op == D3DTOP_SELECTARG1) {
+                    glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);                
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+                    glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);        
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");  
+                } else {
+                    glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);                
+                    checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
+                    glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);        
+                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");  
+                }
+                glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);              
+                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");  
+                glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");  
+                glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);             
+                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+                glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");  
+                break;
+
+	case D3DTOP_ADDSMOOTH:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_COLOR; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_SRC_COLOR; break;
+		case GL_SRC_ALPHA: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr1 = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_BLENDTEXTUREALPHAPM:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEALPHA_ADDCOLOR:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");  /* Add = a0*a1 + a2*a3 */
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);        /*   a0 = src1/opr1    */
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");    /*   a1 = 1 (see docs) */
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);      
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");  
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);        /*   a2 = arg2         */
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");     /*  a3 = src1 alpha   */
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+                case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATECOLOR_ADDALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
+		case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
+		case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
+		switch (opr1) {
+		case GL_SRC_COLOR: opr1 = GL_SRC_ALPHA; break;
+		case GL_ONE_MINUS_SRC_COLOR: opr1 = GL_ONE_MINUS_SRC_ALPHA; break;
+		}
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+	case D3DTOP_MULTIPLYADD:
+		glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
+		checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
+		glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
+		checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
+		glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
+		checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
+		glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
+		checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
+		glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
+		checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
+		glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
+		checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
+		glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
+		checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
+		glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
+		checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
+		glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
+		checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
+		glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
+		checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
+		break;
+
+        default:
+                Handled = FALSE;
+        }
+        if (Handled) {
+	    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
+	    checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
+
+	    LEAVE_GL();
+	    return;
+        }
+#endif /* GL_NV_texture_env_combine4 */
+
+	LEAVE_GL();
+
+        /* After all the extensions, if still unhandled, report fixme */
+        FIXME("Unhandled texture operation %d\n", op);
+}
+#endif
diff -u --new-file /tmp/version.rc dlls/d3dcore/version.rc
--- /tmp/version.rc	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/version.rc	2003-06-20 20:41:28.000000000 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2001 Ove Kaaven
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define WINE_FILEDESCRIPTION_STR "Wine Direct3D core"
+#define WINE_FILENAME_STR "d3dcore.dll"
+#define WINE_FILEVERSION 1,0,0,001
+#define WINE_FILEVERSION_STR "1.0.0.001"
+#define WINE_PRODUCTVERSION 1,0,0,001
+#define WINE_PRODUCTVERSION_STR "1.0"
+#define WINE_PRODUCTNAME_STR "WineD3DCore"
+
+#include "wine/wine_common_ver.rc"
diff -u --new-file /tmp/vertexshader.c dlls/d3dcore/vertexshader.c
--- /tmp/vertexshader.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/vertexshader.c	2003-06-20 20:53:50.000000000 +0200
@@ -0,0 +1,1270 @@
+/*
+ * shaders implementation
+ *
+ * Copyright 2002-2003 Jason Edmeades
+ *                     Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include <math.h>
+
+#include "d3d8.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+
+/* Shader debugging - Change the following line to enable debugging of software
+      vertex shaders                                                             */
+#if 0 /* Must not be 1 in cvs version */
+# define VSTRACE(A) TRACE A
+# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
+#else 
+# define VSTRACE(A) 
+# define TRACE_VSVECTOR(name)
+#endif
+
+
+/**
+ * DirectX9 SDK download
+ *  http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
+ *
+ * Exploring D3DX
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
+ *
+ * Using Vertex Shaders
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
+ *
+ * Dx9 New
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
+ *
+ * Dx9 Shaders
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
+ *
+ * Dx9 D3DX
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
+ *
+ * FVF
+ *  http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
+ *
+ * NVIDIA: DX8 Vertex Shader to NV Vertex Program
+ *  http://developer.nvidia.com/view.asp?IO=vstovp
+ *
+ * NVIDIA: Memory Management with VAR
+ *  http://developer.nvidia.com/view.asp?IO=var_memory_management 
+ */
+
+typedef void (*shader_fct_t)();
+
+typedef struct SHADER_OPCODE {
+  CONST BYTE    opcode;
+  const char*   name;
+  CONST UINT    num_params;
+  shader_fct_t  soft_fct;
+  DWORD         min_version;
+  DWORD         max_version;
+} SHADER_OPCODE;
+
+/*******************************
+ * vshader functions software VM
+ */
+
+void vshader_add(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = s0->x + s1->x;
+  d->y = s0->y + s1->y;
+  d->z = s0->z + s1->z;
+  d->w = s0->w + s1->w;
+  VSTRACE(("executing add: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_dp3(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z;
+  VSTRACE(("executing dp3: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	         s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_dp4(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = d->y = d->z = d->w = s0->x * s1->x + s0->y * s1->y + s0->z * s1->z + s0->w * s1->w;
+  VSTRACE(("executing dp4: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_dst(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = 1.0f;
+  d->y = s0->y * s1->y;
+  d->z = s0->z;
+  d->w = s1->w;
+  VSTRACE(("executing dst: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_expp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  float tmp_f = floorf(s0->w);
+  DWORD tmp_d = 0;
+  tmp_f = powf(2.0f, s0->w);
+  tmp_d = *((DWORD*) &tmp_f) & 0xFFFFFF00;
+
+  d->x  = powf(2.0f, tmp_f);
+  d->y  = s0->w - tmp_f;
+  d->z  = *((float*) &tmp_d);
+  d->w  = 1.0f;
+  VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+                s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_lit(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  d->x = 1.0f;
+  d->y = (0.0f < s0->x) ? s0->x : 0.0f;
+  d->z = (0.0f < s0->x && 0.0f < s0->y) ? powf(s0->y, s0->w) : 0.0f;
+  d->w = 1.0f;
+  VSTRACE(("executing lit: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_logp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  float tmp_f = fabsf(s0->w); 
+  d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE;
+  VSTRACE(("executing logp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	         s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_mad(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D3DSHADERVECTOR* s2) {
+  d->x = s0->x * s1->x + s2->x;
+  d->y = s0->y * s1->y + s2->y;
+  d->z = s0->z * s1->z + s2->z;
+  d->w = s0->w * s1->w + s2->w;
+  VSTRACE(("executing mad: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) s2=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, s2->x, s2->y, s2->z, s2->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_max(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = (s0->x >= s1->x) ? s0->x : s1->x;
+  d->y = (s0->y >= s1->y) ? s0->y : s1->y;
+  d->z = (s0->z >= s1->z) ? s0->z : s1->z;
+  d->w = (s0->w >= s1->w) ? s0->w : s1->w;
+  VSTRACE(("executing max: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_min(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = (s0->x < s1->x) ? s0->x : s1->x;
+  d->y = (s0->y < s1->y) ? s0->y : s1->y;
+  d->z = (s0->z < s1->z) ? s0->z : s1->z;
+  d->w = (s0->w < s1->w) ? s0->w : s1->w;
+  VSTRACE(("executing min: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_mov(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  d->x = s0->x;
+  d->y = s0->y;
+  d->z = s0->z;
+  d->w = s0->w;
+  VSTRACE(("executing mov: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_mul(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = s0->x * s1->x;
+  d->y = s0->y * s1->y;
+  d->z = s0->z * s1->z;
+  d->w = s0->w * s1->w;
+  VSTRACE(("executing mul: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_nop(void) {
+  /* NOPPPP ahhh too easy ;) */
+}
+
+void vshader_rcp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  d->x = d->y = d->z = d->w = (0.0f == s0->w) ? HUGE : 1.0f / s0->w;
+  VSTRACE(("executing rcp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_rsq(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  float tmp_f = fabsf(s0->w);
+  d->x = d->y = d->z = d->w = (0.0f == tmp_f) ? HUGE : ((1.0f != tmp_f) ? 1.0f / sqrtf(tmp_f) : 1.0f);
+  VSTRACE(("executing rsq: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_sge(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = (s0->x >= s1->x) ? 1.0f : 0.0f;
+  d->y = (s0->y >= s1->y) ? 1.0f : 0.0f;
+  d->z = (s0->z >= s1->z) ? 1.0f : 0.0f;
+  d->w = (s0->w >= s1->w) ? 1.0f : 0.0f;
+  VSTRACE(("executing sge: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_slt(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = (s0->x < s1->x) ? 1.0f : 0.0f;
+  d->y = (s0->y < s1->y) ? 1.0f : 0.0f;
+  d->z = (s0->z < s1->z) ? 1.0f : 0.0f;
+  d->w = (s0->w < s1->w) ? 1.0f : 0.0f;
+  VSTRACE(("executing slt: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_sub(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+  d->x = s0->x - s1->x;
+  d->y = s0->y - s1->y;
+  d->z = s0->z - s1->z;
+  d->w = s0->w - s1->w;
+  VSTRACE(("executing sub: s0=(%f, %f, %f, %f) s1=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, s1->x, s1->y, s1->z, s1->w, d->x, d->y, d->z, d->w));
+}
+
+/**
+ * Version 1.1 specific
+ */
+
+void vshader_exp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  d->x = d->y = d->z = d->w = powf(2.0f, s0->w);
+  VSTRACE(("executing exp: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_log(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  float tmp_f = fabsf(s0->w); 
+  d->x = d->y = d->z = d->w = (0.0f != tmp_f) ? logf(tmp_f) / logf(2.0f) : -HUGE;
+  VSTRACE(("executing log: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+void vshader_frc(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+  d->x = s0->x - floorf(s0->x);
+  d->y = s0->y - floorf(s0->y);
+  d->z = 0.0f;
+  d->w = 1.0f;
+  VSTRACE(("executing frc: s0=(%f, %f, %f, %f) => d=(%f, %f, %f, %f)\n",
+	  s0->x, s0->y, s0->z, s0->w, d->x, d->y, d->z, d->w));
+}
+
+typedef FLOAT D3DMATRIX44[4][4];
+typedef FLOAT D3DMATRIX43[4][3];
+typedef FLOAT D3DMATRIX34[4][4];
+typedef FLOAT D3DMATRIX33[4][3];
+typedef FLOAT D3DMATRIX32[4][2];
+
+void vshader_m4x4(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, /*D3DSHADERVECTOR* mat1*/ D3DMATRIX44 mat) {
+  /*
+   * BuGGY CODE: here only if cast not work for copy/paste
+  D3DSHADERVECTOR* mat2 = mat1 + 1;
+  D3DSHADERVECTOR* mat3 = mat1 + 2;
+  D3DSHADERVECTOR* mat4 = mat1 + 3; 
+  d->x = mat1->x * s0->x + mat2->x * s0->y + mat3->x * s0->z + mat4->x * s0->w;
+  d->y = mat1->y * s0->x + mat2->y * s0->y + mat3->y * s0->z + mat4->y * s0->w;
+  d->z = mat1->z * s0->x + mat2->z * s0->y + mat3->z * s0->z + mat4->z * s0->w;
+  d->w = mat1->w * s0->x + mat2->w * s0->y + mat3->w * s0->z + mat4->w * s0->w;
+  */
+  d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
+  d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
+  d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
+  d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z + mat[3][3] * s0->w;
+  VSTRACE(("executing m4x4(1): mat=(%f, %f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
+  VSTRACE(("executing m4x4(2): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
+  VSTRACE(("executing m4x4(3): mat=(%f, %f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
+  VSTRACE(("executing m4x4(4): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], mat[3][3], s0->w, d->w));
+}
+
+void vshader_m4x3(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DMATRIX43 mat) {
+  d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z + mat[0][3] * s0->w;
+  d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z + mat[1][3] * s0->w;
+  d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z + mat[2][3] * s0->w;
+  d->w = 1.0f;
+  VSTRACE(("executing m4x3(1): mat=(%f, %f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], mat[0][3], s0->x, d->x));
+  VSTRACE(("executing m4x3(2): mat=(%f, %f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], mat[1][3], s0->y, d->y));
+  VSTRACE(("executing m4x3(3): mat=(%f, %f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], mat[2][3], s0->z, d->z));
+  VSTRACE(("executing m4x3(4):                            (%f)       (%f) \n", s0->w, d->w));
+}
+
+void vshader_m3x4(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DMATRIX34 mat) {
+  d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
+  d->y = mat[2][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
+  d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
+  d->w = mat[3][0] * s0->x + mat[3][1] * s0->y + mat[3][2] * s0->z;
+  VSTRACE(("executing m3x4(1): mat=(%f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
+  VSTRACE(("executing m3x4(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
+  VSTRACE(("executing m3x4(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
+  VSTRACE(("executing m3x4(4): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[3][0], mat[3][1], mat[3][2], s0->w, d->w));
+}
+
+void vshader_m3x3(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DMATRIX33 mat) {
+  d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[2][2] * s0->z;
+  d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[2][2] * s0->z;
+  d->z = mat[2][0] * s0->x + mat[2][1] * s0->y + mat[2][2] * s0->z;
+  d->w = 1.0f;
+  VSTRACE(("executing m3x3(1): mat=(%f, %f, %f)    s0=(%f)     d=(%f) \n", mat[0][0], mat[0][1], mat[0][2], s0->x, d->x));
+  VSTRACE(("executing m3x3(2): mat=(%f, %f, %f)       (%f)       (%f) \n", mat[1][0], mat[1][1], mat[1][2], s0->y, d->y));
+  VSTRACE(("executing m3x3(3): mat=(%f, %f, %f) X     (%f)  =    (%f) \n", mat[2][0], mat[2][1], mat[2][2], s0->z, d->z));
+  VSTRACE(("executing m3x3(4):                                       (%f) \n", d->w));
+}
+
+void vshader_m3x2(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DMATRIX32 mat) {
+  FIXME("check\n");
+  d->x = mat[0][0] * s0->x + mat[0][1] * s0->y + mat[0][2] * s0->z;
+  d->y = mat[1][0] * s0->x + mat[1][1] * s0->y + mat[1][2] * s0->z;
+  d->z = 0.0f;
+  d->w = 1.0f;
+}
+
+/**
+ * Version 2.0 specific
+ */
+void vshader_lrp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D3DSHADERVECTOR* s2, D3DSHADERVECTOR* s3) {
+  d->x = s0->x * (s1->x - s2->x) + s2->x; 
+  d->y = s0->y * (s1->y - s2->y) + s2->y; 
+  d->z = s0->z * (s1->z - s2->z) + s2->z; 
+  d->w = s0->w * (s1->w - s2->w) + s2->x; 
+}
+
+/**
+ * log, exp, frc, m*x* seems to be macros ins ... to see
+ */
+static CONST SHADER_OPCODE vshader_ins [] = {
+  {D3DSIO_NOP,  "nop",  0, vshader_nop, 0, 0},
+  {D3DSIO_MOV,  "mov",  2, vshader_mov, 0, 0},
+  {D3DSIO_ADD,  "add",  3, vshader_add, 0, 0},
+  {D3DSIO_SUB,  "sub",  3, vshader_sub, 0, 0},
+  {D3DSIO_MAD,  "mad",  4, vshader_mad, 0, 0},
+  {D3DSIO_MUL,  "mul",  3, vshader_mul, 0, 0},
+  {D3DSIO_RCP,  "rcp",  2, vshader_rcp, 0, 0},
+  {D3DSIO_RSQ,  "rsq",  2, vshader_rsq, 0, 0},
+  {D3DSIO_DP3,  "dp3",  3, vshader_dp3, 0, 0},
+  {D3DSIO_DP4,  "dp4",  3, vshader_dp4, 0, 0},
+  {D3DSIO_MIN,  "min",  3, vshader_min, 0, 0},
+  {D3DSIO_MAX,  "max",  3, vshader_max, 0, 0},
+  {D3DSIO_SLT,  "slt",  3, vshader_slt, 0, 0},
+  {D3DSIO_SGE,  "sge",  3, vshader_sge, 0, 0},
+  {D3DSIO_EXP,  "exp",  2, vshader_exp, 0, 0},
+  {D3DSIO_LOG,  "log",  2, vshader_log, 0, 0},
+  {D3DSIO_LIT,  "lit",  2, vshader_lit, 0, 0},
+  {D3DSIO_DST,  "dst",  3, vshader_dst, 0, 0},
+  {D3DSIO_LRP,  "lrp",  5, vshader_lrp, 0, 0},
+  {D3DSIO_FRC,  "frc",  2, vshader_frc, 0, 0},
+  {D3DSIO_M4x4, "m4x4", 3, vshader_m4x4, 0, 0},
+  {D3DSIO_M4x3, "m4x3", 3, vshader_m4x3, 0, 0},
+  {D3DSIO_M3x4, "m3x4", 3, vshader_m3x4, 0, 0},
+  {D3DSIO_M3x3, "m3x3", 3, vshader_m3x3, 0, 0},
+  {D3DSIO_M3x2, "m3x2", 3, vshader_m3x2, 0, 0},
+  /** FIXME: use direct access so add the others opcodes as stubs */
+  {D3DSIO_EXPP, "expp", 2, vshader_expp, 0, 0},
+  {D3DSIO_LOGP, "logp", 2, vshader_logp, 0, 0},
+
+  {0, NULL, 0, NULL, 0, 0}
+};
+
+
+inline static const SHADER_OPCODE* vshader_program_get_opcode(const DWORD code) {
+  DWORD i = 0;
+  /** TODO: use dichotomic search */
+  while (NULL != vshader_ins[i].name) {
+    if ((code & D3DSI_OPCODE_MASK) == vshader_ins[i].opcode) {
+      return &vshader_ins[i];
+    }
+    ++i;
+  }
+  return NULL;
+}
+
+inline static void vshader_program_dump_param(const DWORD param, int input) {
+  static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" };
+  static const char swizzle_reg_chars[] = "xyzw";
+
+  DWORD reg = param & 0x00001FFF;
+  DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+  if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) TRACE("-");
+  
+  switch (regtype << D3DSP_REGTYPE_SHIFT) {
+  case D3DSPR_TEMP:
+    TRACE("R[%lu]", reg);
+    break;
+  case D3DSPR_INPUT:
+    TRACE("V[%lu]", reg);
+    break;
+  case D3DSPR_CONST:
+    TRACE("C[%s%lu]", (reg & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
+    break;
+  case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
+    TRACE("a[%lu]", reg);
+    break;
+  case D3DSPR_RASTOUT:
+    TRACE("%s", rastout_reg_names[reg]);
+    break;
+  case D3DSPR_ATTROUT:
+    TRACE("oD[%lu]", reg);
+    break;
+  case D3DSPR_TEXCRDOUT:
+    TRACE("oT[%lu]", reg);
+    break;
+  default:
+    break;
+  }
+
+  if (!input) {
+    /** operand output */
+    if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
+      if (param & D3DSP_WRITEMASK_0) TRACE(".x");
+      if (param & D3DSP_WRITEMASK_1) TRACE(".y");
+      if (param & D3DSP_WRITEMASK_2) TRACE(".z");
+      if (param & D3DSP_WRITEMASK_3) TRACE(".w");
+    }
+  } else {
+    /** operand input */
+    DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
+    DWORD swizzle_x = swizzle & 0x03;
+    DWORD swizzle_y = (swizzle >> 2) & 0x03;
+    DWORD swizzle_z = (swizzle >> 4) & 0x03;
+    DWORD swizzle_w = (swizzle >> 6) & 0x03;
+    /**
+     * swizzle bits fields:
+     *  WWZZYYXX
+     */
+    if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
+      if (swizzle_x == swizzle_y && 
+	  swizzle_x == swizzle_z && 
+	  swizzle_x == swizzle_w) {
+	TRACE(".%c", swizzle_reg_chars[swizzle_x]);
+      } else {
+	TRACE(".%c%c%c%c", 
+		swizzle_reg_chars[swizzle_x], 
+		swizzle_reg_chars[swizzle_y], 
+		swizzle_reg_chars[swizzle_z], 
+		swizzle_reg_chars[swizzle_w]);
+      }
+    }
+  }
+}
+
+inline static BOOL vshader_is_version_token(DWORD token) {
+  return 0xFFFE0000 == (token & 0xFFFE0000);
+}
+
+inline static BOOL vshader_is_comment_token(DWORD token) {
+  return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
+}
+
+/**
+ * Function parser ...
+ */
+inline static VOID IDirect3DVertexShaderImpl_ParseProgram(IDirect3DVertexShaderImpl* vshader, CONST DWORD* pFunction) {
+  const DWORD* pToken = pFunction;
+  const SHADER_OPCODE* curOpcode = NULL;
+  DWORD len = 0;  
+  DWORD i;
+
+  if (NULL != pToken) {
+    while (D3DVS_END() != *pToken) {
+      if (vshader_is_version_token(*pToken)) { /** version */
+	TRACE("vs.%lu.%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
+	++pToken;
+	++len;
+	continue;
+      } 
+      if (vshader_is_comment_token(*pToken)) { /** comment */
+	DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+	++pToken;
+	/*TRACE("comment[%ld] ;%s\n", comment_len, (char*)pToken);*/
+	pToken += comment_len;
+	len += comment_len + 1;
+	continue;
+      }
+      curOpcode = vshader_program_get_opcode(*pToken);
+      ++pToken;
+      ++len;
+      if (NULL == curOpcode) {
+	/* unkown current opcode ... */
+	while (*pToken & 0x80000000) {
+	  TRACE("unrecognized opcode: %08lx\n", *pToken);
+	  ++pToken;
+	  ++len;
+	}
+      } else {
+	TRACE("%s ", curOpcode->name);
+	if (curOpcode->num_params > 0) {
+	  vshader_program_dump_param(*pToken, 0);
+	  ++pToken;
+	  ++len;
+	  for (i = 1; i < curOpcode->num_params; ++i) {
+	    TRACE(", ");
+	    vshader_program_dump_param(*pToken, 1);
+	    ++pToken;
+	    ++len;
+	  }
+	}
+	TRACE("\n");
+      }
+    }
+    vshader->functionLength = (len + 1) * sizeof(DWORD);
+  } else {
+    vshader->functionLength = 1; /* no Function defined use fixed function vertex processing */
+  }
+  /* copy the function ... because it will certainly be released by application */
+
+  if (NULL != pFunction) {
+    vshader->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, vshader->functionLength);
+    memcpy(vshader->function, pFunction, vshader->functionLength);
+  } else {
+    vshader->function = NULL;
+  }
+}
+
+BOOL IDirect3DVertexShaderImpl_ExecuteHAL(IDirect3DVertexShaderImpl* vshader, VSHADERINPUTDATA* input, VSHADEROUTPUTDATA* output) {
+  /** 
+   * TODO: use the NV_vertex_program (or 1_1) extension 
+   *  and specifics vendors (ARB_vertex_program??) variants for it 
+   */
+  return TRUE;
+}
+
+HRESULT WINAPI IDirect3DVertexShaderImpl_ExecuteSW(IDirect3DVertexShaderImpl* vshader, VSHADERINPUTDATA* input, VSHADEROUTPUTDATA* output) {
+  /** Vertex Shader Temporary Registers */
+  D3DSHADERVECTOR R[12];
+  /*D3DSHADERSCALAR A0;*/
+  D3DSHADERVECTOR A[1];
+  /** temporary Vector for modifier management */
+  D3DSHADERVECTOR d;
+  D3DSHADERVECTOR s[3];
+  /** parser datas */
+  const DWORD* pToken = vshader->function;
+  const SHADER_OPCODE* curOpcode = NULL;
+  /** functions parameters */
+  D3DSHADERVECTOR* p[4];
+  D3DSHADERVECTOR* p_send[4];
+  DWORD i;
+
+  /** init temporary register */
+  memset(R, 0, 12 * sizeof(D3DSHADERVECTOR));
+
+  /* vshader_program_parse(vshader); */
+#if 0 /* Must not be 1 in cvs */
+  TRACE("Input:\n");
+  TRACE_VSVECTOR(vshader->data->C[0]);
+  TRACE_VSVECTOR(vshader->data->C[1]);
+  TRACE_VSVECTOR(vshader->data->C[2]);
+  TRACE_VSVECTOR(vshader->data->C[3]);
+  TRACE_VSVECTOR(vshader->data->C[4]);
+  TRACE_VSVECTOR(vshader->data->C[5]);
+  TRACE_VSVECTOR(vshader->data->C[6]);
+  TRACE_VSVECTOR(vshader->data->C[7]);
+  TRACE_VSVECTOR(vshader->data->C[8]);
+  TRACE_VSVECTOR(vshader->data->C[64]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_POSITION]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_BLENDWEIGHT]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_BLENDINDICES]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_NORMAL]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_PSIZE]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_DIFFUSE]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_SPECULAR]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD0]);
+  TRACE_VSVECTOR(input->V[D3DVSDE_TEXCOORD1]);
+#endif
+
+  TRACE_VSVECTOR(vshader->data->C[64]);
+
+  /* the first dword is the version tag */
+  /* TODO: parse it */
+  
+  if (vshader_is_version_token(*pToken)) { /** version */
+    ++pToken;
+  }
+  while (D3DVS_END() != *pToken) {
+    if (vshader_is_comment_token(*pToken)) { /** comment */
+      DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+      ++pToken;
+      pToken += comment_len;
+      continue ;
+    }
+    curOpcode = vshader_program_get_opcode(*pToken);
+    ++pToken;
+    if (NULL == curOpcode) {
+      i = 0;
+      /* unkown current opcode ... */
+      while (*pToken & 0x80000000) {
+	if (i == 0) {
+	  TRACE("unrecognized opcode: pos=%d token=%08lX\n", (pToken - 1) - vshader->function, *(pToken - 1));
+	}
+	TRACE("unrecognized opcode param: pos=%d token=%08lX what=", pToken - vshader->function, *pToken);
+	vshader_program_dump_param(*pToken, i);
+	TRACE("\n");
+	++i;
+	++pToken;
+      }
+      /*return FALSE;*/
+    } else {     
+      if (curOpcode->num_params > 0) {	
+	/*TRACE(">> execting opcode: pos=%d opcode_name=%s token=%08lX\n", pToken - vshader->function, curOpcode->name, *pToken);*/
+	for (i = 0; i < curOpcode->num_params; ++i) {
+	  DWORD reg = pToken[i] & 0x00001FFF;
+	  DWORD regtype = ((pToken[i] & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+	  switch (regtype << D3DSP_REGTYPE_SHIFT) {
+	  case D3DSPR_TEMP:
+	    /*TRACE("p[%d]=R[%d]\n", i, reg);*/
+	    p[i] = &R[reg];
+	    break;
+	  case D3DSPR_INPUT:
+	    /*TRACE("p[%d]=V[%s]\n", i, VertexShaderDeclRegister[reg]);*/
+	    p[i] = &input->V[reg];
+	    break;
+	  case D3DSPR_CONST:
+	    if (reg & D3DVS_ADDRMODE_RELATIVE) {
+	      p[i] = &vshader->data->C[(DWORD) A[0].x + reg];
+	    } else {
+	      p[i] = &vshader->data->C[reg];
+	    }
+	    break;
+	  case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/
+	    if (0 != reg) {
+	      ERR("cannot handle address registers != a0, forcing use of a0\n");
+	      reg = 0;
+	    }
+	    /*TRACE("p[%d]=A[%d]\n", i, reg);*/
+	    p[i] = &A[reg];
+	    break;
+	  case D3DSPR_RASTOUT:
+	    switch (reg) {
+	    case D3DSRO_POSITION:
+	      p[i] = &output->oPos;
+	      break;
+	    case D3DSRO_FOG:
+	      p[i] = &output->oFog;
+	      break;
+	    case D3DSRO_POINT_SIZE:
+	      p[i] = &output->oPts;
+	      break;
+	    }
+	    break;
+	  case D3DSPR_ATTROUT:
+	    /*TRACE("p[%d]=oD[%d]\n", i, reg);*/
+	    p[i] = &output->oD[reg];
+	    break;
+	  case D3DSPR_TEXCRDOUT:
+	    /*TRACE("p[%d]=oT[%d]\n", i, reg);*/
+	    p[i] = &output->oT[reg];
+	    break;
+	  default:
+	    break;
+	  }
+	  
+	  if (i > 0) { /* input reg */
+	    DWORD swizzle = (pToken[i] & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
+	    UINT isNegative = ((pToken[i] & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG);
+
+	    if (!isNegative && (D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) {
+	      /*TRACE("p[%d] not swizzled\n", i);*/
+	      p_send[i] = p[i];
+	    } else {
+	      DWORD swizzle_x = swizzle & 0x03;
+	      DWORD swizzle_y = (swizzle >> 2) & 0x03;
+	      DWORD swizzle_z = (swizzle >> 4) & 0x03;
+	      DWORD swizzle_w = (swizzle >> 6) & 0x03;
+	      /*TRACE("p[%d] swizzled\n", i);*/
+	      float* tt = (float*) p[i];
+	      s[i].x = (isNegative) ? -tt[swizzle_x] : tt[swizzle_x];
+	      s[i].y = (isNegative) ? -tt[swizzle_y] : tt[swizzle_y];
+	      s[i].z = (isNegative) ? -tt[swizzle_z] : tt[swizzle_z];
+	      s[i].w = (isNegative) ? -tt[swizzle_w] : tt[swizzle_w];
+	      p_send[i] = &s[i];
+	    }
+	  } else { /* output reg */
+	    if ((pToken[i] & D3DSP_WRITEMASK_ALL) == D3DSP_WRITEMASK_ALL) {
+	      p_send[i] = p[i];
+	    } else {
+	      p_send[i] = &d; /* to be post-processed for modifiers management */
+	    }
+	  }
+	}      
+      }
+
+      switch (curOpcode->num_params) {	
+      case 0:
+	curOpcode->soft_fct();
+	break;
+      case 1:
+	curOpcode->soft_fct(p_send[0]);
+	break;
+      case 2:
+	curOpcode->soft_fct(p_send[0], p_send[1]);
+	break;
+      case 3:
+	curOpcode->soft_fct(p_send[0], p_send[1], p_send[2]);
+	break;
+      case 4:
+	curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3]);
+	break;
+      case 5:
+	curOpcode->soft_fct(p_send[0], p_send[1], p_send[2], p_send[3], p_send[4]);
+	break;
+      default:
+	ERR("%s too many params: %u\n", curOpcode->name, curOpcode->num_params);
+      }
+
+      /* check if output reg modifier post-process */
+      if (curOpcode->num_params > 0 && (pToken[0] & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
+	if (pToken[0] & D3DSP_WRITEMASK_0) p[0]->x = d.x; 
+	if (pToken[0] & D3DSP_WRITEMASK_1) p[0]->y = d.y; 
+	if (pToken[0] & D3DSP_WRITEMASK_2) p[0]->z = d.z; 
+	if (pToken[0] & D3DSP_WRITEMASK_3) p[0]->w = d.w; 
+      }
+      
+#if 0
+      TRACE_VSVECTOR(output->oPos);
+      TRACE_VSVECTOR(output->oD[0]);
+      TRACE_VSVECTOR(output->oD[1]);
+      TRACE_VSVECTOR(output->oT[0]);
+      TRACE_VSVECTOR(output->oT[1]);
+      TRACE_VSVECTOR(R[0]);
+      TRACE_VSVECTOR(R[1]);
+      TRACE_VSVECTOR(R[2]);
+      TRACE_VSVECTOR(R[3]);
+      TRACE_VSVECTOR(R[4]);
+      TRACE_VSVECTOR(R[5]);
+#endif
+
+      /* to next opcode token */
+      pToken += curOpcode->num_params;
+    }
+#if 0
+    TRACE("End of current instruction:\n");
+    TRACE_VSVECTOR(output->oPos);
+    TRACE_VSVECTOR(output->oD[0]);
+    TRACE_VSVECTOR(output->oD[1]);
+    TRACE_VSVECTOR(output->oT[0]);
+    TRACE_VSVECTOR(output->oT[1]);
+    TRACE_VSVECTOR(R[0]);
+    TRACE_VSVECTOR(R[1]);
+    TRACE_VSVECTOR(R[2]);
+    TRACE_VSVECTOR(R[3]);
+    TRACE_VSVECTOR(R[4]);
+    TRACE_VSVECTOR(R[5]);
+#endif
+  }
+#if 0 /* Must not be 1 in cvs */
+    TRACE("Output:\n");
+    TRACE_VSVECTOR(output->oPos);
+    TRACE_VSVECTOR(output->oD[0]);
+    TRACE_VSVECTOR(output->oD[1]);
+    TRACE_VSVECTOR(output->oT[0]);
+    TRACE_VSVECTOR(output->oT[1]);
+#endif
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DVertexShaderImpl_GetFunction(IDirect3DVertexShaderImpl* This, VOID* pData, UINT* pSizeOfData) {
+  if (NULL == pData) {
+    *pSizeOfData = This->functionLength;
+    return D3D_OK;
+  }
+  if (*pSizeOfData < This->functionLength) {
+    *pSizeOfData = This->functionLength;
+    return D3DERR_MOREDATA;
+  }
+  if (NULL == This->function) { /* no function defined */
+    TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
+    (*(DWORD **) pData) = NULL;
+  } else {
+    TRACE("(%p) : GetFunction copying to %p\n", This, pData);
+    memcpy(pData, This->function, This->functionLength);
+  }
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DVertexShaderImpl_SetConstantF(IDirect3DVertexShaderImpl* This, UINT StartRegister, CONST FLOAT* pConstantData, UINT Vector4fCount) {
+  if (StartRegister + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
+    return D3DERR_INVALIDCALL;
+  }
+  if (NULL == This->data) { /* temporary while datas not supported */
+    FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This);
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(&This->data->C[StartRegister], pConstantData, Vector4fCount * 4 * sizeof(FLOAT));
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DVertexShaderImpl_GetConstantF(IDirect3DVertexShaderImpl* This, UINT StartRegister, FLOAT* pConstantData, UINT Vector4fCount) {
+  if (StartRegister + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
+    return D3DERR_INVALIDCALL;
+  }
+  if (NULL == This->data) { /* temporary while datas not supported */
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(pConstantData, &This->data->C[StartRegister], Vector4fCount * 4 * sizeof(FLOAT));
+  return D3D_OK;
+}
+
+
+/**********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************/
+
+void pshader_texcoord(D3DSHADERVECTOR* d) {
+}
+
+void pshader_texkill(D3DSHADERVECTOR* d) {
+}
+
+void pshader_tex(D3DSHADERVECTOR* d) {
+}
+
+void pshader_texbem(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texbeml(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texreg2ar(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texreg2gb(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x2pad(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x2tex(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x3pad(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x3tex(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x3diff(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x3spec(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+}
+
+void pshader_texm3x3vspec(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_cnd(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D3DSHADERVECTOR* s2) {
+}
+
+void pshader_def(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D3DSHADERVECTOR* s2, D3DSHADERVECTOR* s3) {
+}
+
+void pshader_texreg2rgb(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texdp3tex(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x2depth(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texdp3(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texm3x3(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0) {
+}
+
+void pshader_texdepth(D3DSHADERVECTOR* d) {
+}
+
+void pshader_cmp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D3DSHADERVECTOR* s2) {
+}
+
+void pshader_bem(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1) {
+}
+
+static CONST SHADER_OPCODE pshader_ins [] = {
+  {D3DSIO_NOP,  "nop",  0, vshader_nop, 0, 0},
+  {D3DSIO_MOV,  "mov",  2, vshader_mov, 0, 0},
+  {D3DSIO_ADD,  "add",  3, vshader_add, 0, 0},
+  {D3DSIO_SUB,  "sub",  3, vshader_sub, 0, 0},
+  {D3DSIO_MAD,  "mad",  4, vshader_mad, 0, 0},
+  {D3DSIO_MUL,  "mul",  3, vshader_mul, 0, 0},
+  {D3DSIO_RCP,  "rcp",  2, vshader_rcp, 0, 0},
+  {D3DSIO_RSQ,  "rsq",  2, vshader_rsq, 0, 0},
+  {D3DSIO_DP3,  "dp3",  3, vshader_dp3, 0, 0},
+  {D3DSIO_DP4,  "dp4",  3, vshader_dp4, 0, 0},
+  {D3DSIO_MIN,  "min",  3, vshader_min, 0, 0},
+  {D3DSIO_MAX,  "max",  3, vshader_max, 0, 0},
+  {D3DSIO_SLT,  "slt",  3, vshader_slt, 0, 0},
+  {D3DSIO_SGE,  "sge",  3, vshader_sge, 0, 0},
+  {D3DSIO_EXP,  "exp",  2, vshader_exp, 0, 0},
+  {D3DSIO_LOG,  "log",  2, vshader_log, 0, 0},
+  {D3DSIO_LIT,  "lit",  2, vshader_lit, 0, 0},
+  {D3DSIO_DST,  "dst",  3, vshader_dst, 0, 0},
+  {D3DSIO_LRP,  "lrp",  5, vshader_lrp, 0, 0},
+  {D3DSIO_FRC,  "frc",  2, vshader_frc, 0, 0},
+  {D3DSIO_M4x4, "m4x4", 3, vshader_m4x4, 0, 0},
+  {D3DSIO_M4x3, "m4x3", 3, vshader_m4x3, 0, 0},
+  {D3DSIO_M3x4, "m3x4", 3, vshader_m3x4, 0, 0},
+  {D3DSIO_M3x3, "m3x3", 3, vshader_m3x3, 0, 0},
+  {D3DSIO_M3x2, "m3x2", 3, vshader_m3x2, 0, 0},
+
+  {D3DSIO_TEXCOORD,     "texcoord",     1, pshader_texcoord,     D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
+  {D3DSIO_TEXKILL,      "texkill",      1, pshader_texkill,      D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)},
+  {D3DSIO_TEX,          "tex",          1, pshader_tex,          D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)}, 
+  {D3DSIO_TEXBEM,       "texbem",       2, pshader_texbem,       D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXBEML,      "texbeml",      2, pshader_texbeml,      D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXREG2AR,    "texreg2ar",    2, pshader_texreg2ar,    D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXREG2GB,    "texreg2gb",    2, pshader_texreg2gb,    D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x2PAD,   "texm3x2pad",   2, pshader_texm3x2pad,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x2TEX,   "texm3x2tex",   2, pshader_texm3x2tex,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x3PAD,   "texm3x3pad",   2, pshader_texm3x3pad,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x3TEX,   "texm3x3tex",   2, pshader_texm3x3tex,   D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x3DIFF,  "texm3x3diff",  2, pshader_texm3x3diff,  D3DPS_VERSION(0,0), D3DPS_VERSION(0,0)}, 
+  {D3DSIO_TEXM3x3SPEC,  "texm3x3spec",  3, pshader_texm3x3spec,  D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x3VSPEC, "texm3x3vspec", 2, pshader_texm3x3vspec, D3DPS_VERSION(1,1), D3DPS_VERSION(1,3)}, 
+
+  {D3DSIO_EXPP,         "expp",         2, vshader_expp, 0, 0},
+  {D3DSIO_LOGP,         "logp",         2, vshader_logp, 0, 0},
+
+  {D3DSIO_CND,          "cnd",          4, pshader_cnd,          D3DPS_VERSION(1,1), D3DPS_VERSION(1,4)},
+  {D3DSIO_DEF,          "def",          5, pshader_def,          D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)},
+  {D3DSIO_TEXREG2RGB,   "texbreg2rgb",  2, pshader_texreg2rgb,   D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, 
+  
+  {D3DSIO_TEXDP3TEX,    "texdp3tex",    2, pshader_texdp3tex,    D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x2DEPTH, "texm3x2depth", 2, pshader_texm3x2depth, D3DPS_VERSION(1,3), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXDP3,       "texdp3",       2, pshader_texdp3,       D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)}, 
+  {D3DSIO_TEXM3x3,      "texm3x3",      2, pshader_texm3x3,      D3DPS_VERSION(1,2), D3DPS_VERSION(1,3)},
+  {D3DSIO_TEXDEPTH,     "texdepth",     1, pshader_texdepth,     D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)},
+  {D3DSIO_CMP,          "cmp",          4, pshader_cmp,          D3DPS_VERSION(1,1), D3DPS_VERSION(3,0)}, 
+  {D3DSIO_BEM,          "bem",          3, pshader_bem,          D3DPS_VERSION(1,4), D3DPS_VERSION(1,4)}, 
+
+  {0, NULL, 0, NULL}
+};
+
+inline static const SHADER_OPCODE* pshader_program_get_opcode(const DWORD code) {
+  DWORD i = 0;
+  /** TODO: use dichotomic search */
+  while (NULL != pshader_ins[i].name) {
+    if ((code & D3DSI_OPCODE_MASK) == pshader_ins[i].opcode) {
+      return &pshader_ins[i];
+    }
+    ++i;
+  }
+  return NULL;
+}
+
+inline static void pshader_program_dump_opcode(const SHADER_OPCODE* curOpcode, const DWORD code, const DWORD output) {
+  if (0 != (code & ~D3DSI_OPCODE_MASK)) {
+    DWORD mask = (code & ~D3DSI_OPCODE_MASK);
+    switch (mask) {
+    case 0x40000000:    TRACE("+"); break;
+    default:
+      TRACE(" unhandled modifier(0x%08lx) ", mask);
+    }
+  }
+  TRACE("%s", curOpcode->name);
+  /**
+   * normally this is a destination reg modifier 
+   * but in pixel shaders asm code its specified as:
+   *  dp3_x4 t1.rgba, r1, c1
+   * or
+   *  dp3_x2_sat r0, t0_bx2, v0_bx2
+   * so for better debbuging i use the same norm
+   */
+  if (0 != (output & D3DSP_DSTSHIFT_MASK)) {
+    DWORD shift = (output & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
+    if (shift > 0) {
+      TRACE("_x%u", 1 << shift);
+    }
+  } 
+  /**
+   * TODO: fix the divide shifts: d2, d4, d8
+   *  so i have to find a sample
+   */
+  if (0 != (output & D3DSP_DSTMOD_MASK)) {
+    DWORD mask = output & D3DSP_DSTMOD_MASK;
+    switch (mask) {
+    case D3DSPDM_SATURATE: TRACE("_sat"); break;
+    default:
+      TRACE("_unhandled_modifier(0x%08lx)", mask);
+    }
+  }
+  TRACE(" ");
+}
+
+inline static void pshader_program_dump_param(const DWORD param, int input) {
+  static const char* rastout_reg_names[] = { "oC0", "oC1", "oC2", "oC3", "oDepth" };
+  static const char swizzle_reg_chars[] = "rgba";
+
+  DWORD reg = param & 0x00001FFF;
+  DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+
+  if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) {
+    TRACE("-");
+  }
+  
+  switch (regtype << D3DSP_REGTYPE_SHIFT) {
+  case D3DSPR_TEMP:
+    TRACE("R[%lu]", reg);
+    break;
+  case D3DSPR_INPUT:
+    TRACE("V[%lu]", reg);
+    break;
+  case D3DSPR_CONST:
+    TRACE("C[%s%lu]", (reg & D3DVS_ADDRMODE_RELATIVE) ? "a0.x + " : "", reg);
+    break;
+  case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
+    TRACE("t[%lu]", reg);
+    break;
+  case D3DSPR_RASTOUT:
+    TRACE("%s", rastout_reg_names[reg]);
+    break;
+  case D3DSPR_ATTROUT:
+    TRACE("oD[%lu]", reg);
+    break;
+  case D3DSPR_TEXCRDOUT:
+    TRACE("oT[%lu]", reg);
+    break;
+  default:
+    break;
+  }
+
+  if (!input) {
+    /** operand output */
+    /**
+     * for better debugging traces it's done into opcode dump code
+     * @see pshader_program_dump_opcode
+    if (0 != (param & D3DSP_DSTMOD_MASK)) {
+      DWORD mask = param & D3DSP_DSTMOD_MASK;
+      switch (mask) {
+      case D3DSPDM_SATURATE: TRACE("_sat"); break;
+      default:
+      TRACE("_unhandled_modifier(0x%08lx)", mask);
+      }
+    }
+    if (0 != (param & D3DSP_DSTSHIFT_MASK)) {
+      DWORD shift = (param & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
+      if (shift > 0) {
+	TRACE("_x%u", 1 << shift);
+      }
+    }
+    */
+    if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
+      if (param & D3DSP_WRITEMASK_0) TRACE(".r");
+      if (param & D3DSP_WRITEMASK_1) TRACE(".g");
+      if (param & D3DSP_WRITEMASK_2) TRACE(".b");
+      if (param & D3DSP_WRITEMASK_3) TRACE(".a");
+    }
+  } else {
+    /** operand input */
+    DWORD swizzle = (param & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
+    DWORD swizzle_x = swizzle & 0x03;
+    DWORD swizzle_y = (swizzle >> 2) & 0x03;
+    DWORD swizzle_z = (swizzle >> 4) & 0x03;
+    DWORD swizzle_w = (swizzle >> 6) & 0x03;
+    /**
+     * swizzle bits fields:
+     *  WWZZYYXX
+     */
+    if ((D3DSP_NOSWIZZLE >> D3DSP_SWIZZLE_SHIFT) != swizzle) { /* ! D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
+      if (swizzle_x == swizzle_y && 
+	  swizzle_x == swizzle_z && 
+	  swizzle_x == swizzle_w) {
+	TRACE(".%c", swizzle_reg_chars[swizzle_x]);
+      } else {
+	TRACE(".%c%c%c%c", 
+	      swizzle_reg_chars[swizzle_x], 
+	      swizzle_reg_chars[swizzle_y], 
+	      swizzle_reg_chars[swizzle_z], 
+	      swizzle_reg_chars[swizzle_w]);
+      }
+    }
+    if (0 != (param & D3DSP_SRCMOD_MASK)) {
+      DWORD mask = param & D3DSP_SRCMOD_MASK;
+      /*TRACE("_modifier(0x%08lx) ", mask);*/
+      switch (mask) {
+      case D3DSPSM_NONE:    break;
+      case D3DSPSM_NEG:     break;
+      case D3DSPSM_BIAS:    TRACE("_bias"); break;
+      case D3DSPSM_BIASNEG: TRACE("_bias"); break;
+      case D3DSPSM_SIGN:    TRACE("_sign"); break;
+      case D3DSPSM_SIGNNEG: TRACE("_sign"); break;
+      case D3DSPSM_COMP:    TRACE("_comp"); break;
+      case D3DSPSM_X2:      TRACE("_x2"); break;
+      case D3DSPSM_X2NEG:   TRACE("_bx2"); break;
+      case D3DSPSM_DZ:      TRACE("_dz"); break;
+      case D3DSPSM_DW:      TRACE("_dw"); break;
+      default:
+	TRACE("_unknown(0x%08lx)", mask);
+      }
+    }
+  }
+}
+
+inline static BOOL pshader_is_version_token(DWORD token) {
+  return 0xFFFF0000 == (token & 0xFFFF0000);
+}
+
+inline static BOOL pshader_is_comment_token(DWORD token) {
+  return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
+}
+
+
+
+/**
+ * Pixel Shaders
+ *
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/PixelShader1_X/modifiers/sourceregistermodifiers.asp
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/PixelShader2_0/Registers/Registers.asp
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/IDirect3DPixelShader9/_IDirect3DPixelShader9.asp
+ *
+ */
+inline static VOID IDirect3DPixelShaderImpl_ParseProgram(IDirect3DPixelShaderImpl* pshader, CONST DWORD* pFunction) {
+  const DWORD* pToken = pFunction;
+  const SHADER_OPCODE* curOpcode = NULL;
+  DWORD code;
+  DWORD len = 0;  
+  DWORD i;
+
+  if (NULL != pToken) {
+    while (D3DPS_END() != *pToken) { 
+      if (pshader_is_version_token(*pToken)) { /** version */
+	TRACE("ps.%lu.%lu\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F));
+	++pToken;
+	++len;
+	continue;
+      } 
+      if (pshader_is_comment_token(*pToken)) { /** comment */
+	DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+	++pToken;
+	/*TRACE("comment[%ld] ;%s\n", comment_len, (char*)pToken);*/
+	pToken += comment_len;
+	len += comment_len + 1;
+	continue;
+      }
+      code = *pToken;
+      curOpcode = pshader_program_get_opcode(code);
+      ++pToken;
+      ++len;
+      if (NULL == curOpcode) {
+	/* unkown current opcode ... */
+	while (*pToken & 0x80000000) {
+	  TRACE("unrecognized opcode: %08lx\n", *pToken);
+	  ++pToken;
+	  ++len;
+	}
+      } else {
+	TRACE(" ");
+	pshader_program_dump_opcode(curOpcode, code, *pToken);
+	if (curOpcode->num_params > 0) {
+	  pshader_program_dump_param(*pToken, 0);
+	  ++pToken;
+	  ++len;
+	  for (i = 1; i < curOpcode->num_params; ++i) {
+	    TRACE(", ");
+	    if (D3DSIO_DEF != code) {
+	      pshader_program_dump_param(*pToken, 1);
+	    } else {
+	      TRACE("%f", *((float*) pToken));
+	    }
+	    ++pToken;
+	    ++len;
+	  }
+	}
+	TRACE("\n");
+      }
+      pshader->functionLength = (len + 1) * sizeof(DWORD);
+    } 
+  } else {
+    pshader->functionLength = 1; /* no Function defined use fixed function vertex processing */
+  }
+  if (NULL != pFunction) {
+    pshader->function = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pshader->functionLength);
+    memcpy(pshader->function, pFunction, pshader->functionLength);
+  } else {
+    pshader->function = NULL;
+  }
+}
+
+HRESULT WINAPI IDirect3DPixelShaderImpl_GetFunction(IDirect3DPixelShaderImpl* This, VOID* pData, UINT* pSizeOfData) {
+  if (NULL == pData) {
+    *pSizeOfData = This->functionLength;
+    return D3D_OK;
+  }
+  if (*pSizeOfData < This->functionLength) {
+    *pSizeOfData = This->functionLength;
+    return D3DERR_MOREDATA;
+  }
+  if (NULL == This->function) { /* no function defined */
+    TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
+    (*(DWORD **) pData) = NULL;
+  } else {
+    TRACE("(%p) : GetFunction copying to %p\n", This, pData);
+    memcpy(pData, This->function, This->functionLength);
+  }
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DPixelShaderImpl_SetConstantF(IDirect3DPixelShaderImpl* This, UINT StartRegister, CONST FLOAT* pConstantData, UINT Vector4fCount) {
+  if (StartRegister + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
+    return D3DERR_INVALIDCALL;
+  }
+  if (NULL == This->data) { /* temporary while datas not supported */
+    FIXME("(%p) : VertexShader_SetConstant not fully supported yet\n", This);
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(&This->data->C[StartRegister], pConstantData, Vector4fCount * 4 * sizeof(FLOAT));
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DPixelShaderImpl_GetConstantF(IDirect3DPixelShaderImpl* This, UINT StartRegister, FLOAT* pConstantData, UINT Vector4fCount) {
+  if (StartRegister + Vector4fCount > D3D_VSHADER_MAX_CONSTANTS) {
+    return D3DERR_INVALIDCALL;
+  }
+  if (NULL == This->data) { /* temporary while datas not supported */
+    return D3DERR_INVALIDCALL;
+  }
+  memcpy(pConstantData, &This->data->C[StartRegister], Vector4fCount * 4 * sizeof(FLOAT));
+  return D3D_OK;
+}
+
+/**********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************
+ **********************************************************************************************************************************************/
+
+/***********************************************************************
+ *		ValidateVertexShader (D3D8.@)
+ */
+BOOL WINAPI ValidateVertexShader(LPVOID what, LPVOID toto) {
+  FIXME("(void): stub: %p %p\n", what, toto);
+  return TRUE;
+}
+
+/***********************************************************************
+ *		ValidatePixelShader (D3D8.@)
+ */
+BOOL WINAPI ValidatePixelShader(LPVOID what, LPVOID toto) {
+  FIXME("(void): stub: %p %p\n", what, toto);
+  return TRUE;
+}
diff -u --new-file /tmp/vertexshaderdeclaration.c dlls/d3dcore/vertexshaderdeclaration.c
--- /tmp/vertexshaderdeclaration.c	1970-01-01 01:00:00.000000000 +0100
+++ dlls/d3dcore/vertexshaderdeclaration.c	2003-06-20 20:57:46.000000000 +0200
@@ -0,0 +1,577 @@
+/*
+ * vertex shaders declaration implementation
+ *
+ * Copyright 2002 Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "wingdi.h"
+#include "wine/debug.h"
+
+#include <math.h>
+
+#include "d3d8.h"
+#include "d3dcore_interface.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
+
+/**
+ * DirectX9 SDK download
+ *  http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp
+ *
+ * Exploring D3DX
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx07162002.asp
+ *
+ * Using Vertex Shaders
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndrive/html/directx02192001.asp
+ *
+ * Dx9 New
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/whatsnew.asp
+ *
+ * Dx9 Shaders
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/VertexShader2_0.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader2_0/Instructions/Instructions.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexDeclaration/VertexDeclaration.asp
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/Shaders/VertexShader3_0/VertexShader3_0.asp
+ *
+ * Dx9 D3DX
+ *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/advancedtopics/VertexPipe/matrixstack/matrixstack.asp
+ *
+ * FVF
+ *  http://msdn.microsoft.com/library/en-us/directx9_c/directx/graphics/programmingguide/GettingStarted/VertexFormats/vformats.asp
+ *
+ * NVIDIA: DX8 Vertex Shader to NV Vertex Program
+ *  http://developer.nvidia.com/view.asp?IO=vstovp
+ *
+ * NVIDIA: Memory Management with VAR
+ *  http://developer.nvidia.com/view.asp?IO=var_memory_management 
+ */
+
+/** Vertex Shader Declaration data types tokens */
+#define MAX_VSHADER_DECL_TYPES 8
+static CONST char* VertexShaderDeclDataTypes[] = {
+  "D3DVSDT_FLOAT1",
+  "D3DVSDT_FLOAT2",
+  "D3DVSDT_FLOAT3",
+  "D3DVSDT_FLOAT4",
+  "D3DVSDT_D3DCOLOR",
+  "D3DVSDT_UBYTE4",
+  "D3DVSDT_SHORT2",
+  "D3DVSDT_SHORT4",
+  NULL
+};
+
+static CONST char* VertexShaderDeclRegister[] = {
+  "D3DVSDE_POSITION",
+  "D3DVSDE_BLENDWEIGHT",
+  "D3DVSDE_BLENDINDICES",
+  "D3DVSDE_NORMAL",
+  "D3DVSDE_PSIZE",
+  "D3DVSDE_DIFFUSE",
+  "D3DVSDE_SPECULAR",
+  "D3DVSDE_TEXCOORD0",
+  "D3DVSDE_TEXCOORD1",
+  "D3DVSDE_TEXCOORD2",
+  "D3DVSDE_TEXCOORD3",
+  "D3DVSDE_TEXCOORD4",
+  "D3DVSDE_TEXCOORD5",
+  "D3DVSDE_TEXCOORD6",
+  "D3DVSDE_TEXCOORD7",
+  "D3DVSDE_POSITION2",
+  "D3DVSDE_NORMAL2",
+  NULL
+};
+
+/** todo check decl validity */
+/*inline static*/ DWORD Direct3DVextexShaderDeclarationImpl_ParseToken(const DWORD* pToken) {
+  const DWORD token = *pToken;
+  DWORD tokenlen = 1;
+
+  switch ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT) { /* maybe a macro to inverse ... */
+  case D3DVSD_TOKEN_NOP:
+    TRACE(" 0x%08lx NOP()\n", token);
+    break;
+  case D3DVSD_TOKEN_STREAM:
+    if (token & D3DVSD_STREAMTESSMASK) {
+      TRACE(" 0x%08lx STREAM_TESS()\n", token);
+    } else {
+      TRACE(" 0x%08lx STREAM(%lu)\n", token, ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT));
+    }
+    break;
+  case D3DVSD_TOKEN_STREAMDATA:
+    if (token & 0x10000000) {
+      TRACE(" 0x%08lx SKIP(%lu)\n", token, ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT));
+    } else {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      TRACE(" 0x%08lx REG(%s, %s)\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]);
+    }
+    break;
+  case D3DVSD_TOKEN_TESSELLATOR:
+    if (token & 0x10000000) {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      TRACE(" 0x%08lx TESSUV(%s) as %s\n", token, VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]);
+    } else {
+      DWORD type   = ((token & D3DVSD_DATATYPEMASK)    >> D3DVSD_DATATYPESHIFT);
+      DWORD regout = ((token & D3DVSD_VERTEXREGMASK)   >> D3DVSD_VERTEXREGSHIFT);
+      DWORD regin  = ((token & D3DVSD_VERTEXREGINMASK) >> D3DVSD_VERTEXREGINSHIFT);
+      TRACE(" 0x%08lx TESSNORMAL(%s, %s) as %s\n", token, VertexShaderDeclRegister[regin], VertexShaderDeclRegister[regout], VertexShaderDeclDataTypes[type]);
+    }
+    break;
+  case D3DVSD_TOKEN_CONSTMEM:
+    {
+      DWORD i;
+      DWORD count        = ((token & D3DVSD_CONSTCOUNTMASK)   >> D3DVSD_CONSTCOUNTSHIFT);
+      DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
+      TRACE(" 0x%08lx CONST(%lu, %lu)\n", token, constaddress, count);
+      ++pToken;
+      for (i = 0; i < count; ++i) {
+#if 0
+	TRACE("        c[%lu] = (0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", 
+		constaddress, 
+		*pToken, 
+		*(pToken + 1), 
+		*(pToken + 2), 
+		*(pToken + 3));
+#endif
+	TRACE("        c[%lu] = (%8f, %8f, %8f, %8f)\n", 
+		constaddress, 
+		 *(float*) pToken, 
+		 *(float*) (pToken + 1), 
+		 *(float*) (pToken + 2), 
+		 *(float*) (pToken + 3));
+	pToken += 4; 
+	++constaddress;
+      }
+      tokenlen = (4 * count) + 1;
+    }
+    break;
+  case D3DVSD_TOKEN_EXT:
+    {
+      DWORD count   = ((token & D3DVSD_CONSTCOUNTMASK) >> D3DVSD_CONSTCOUNTSHIFT);
+      DWORD extinfo = ((token & D3DVSD_EXTINFOMASK)    >> D3DVSD_EXTINFOSHIFT);
+      TRACE(" 0x%08lx EXT(%lu, %lu)\n", token, count, extinfo);
+      /* todo ... print extension */
+      tokenlen = count + 1;
+    }
+    break;
+  case D3DVSD_TOKEN_END:
+    TRACE(" 0x%08lx END()\n", token);
+    break;
+  default:
+    TRACE(" 0x%08lx UNKNOWN\n", token);
+    /* argg error */
+  }
+  return tokenlen;
+}
+
+HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(IDirect3DDeviceImpl* This, CONST DWORD* pDeclaration8, IDirect3DVertexShaderDeclarationImpl** ppVertexShaderDecl) {
+  /** parser data */
+  const DWORD* pToken = pDeclaration8;
+  DWORD fvf = 0;
+  DWORD len = 0;  
+  DWORD stream = 0;
+  DWORD token;
+  DWORD tokenlen;
+  DWORD tokentype;
+  DWORD tex = D3DFVF_TEX0;
+  /** TRUE if declaration can be matched by a fvf */
+  IDirect3DVertexShaderDeclarationImpl* object;
+  BOOL  invalid_fvf = FALSE;
+
+  TRACE("(%p) :  pDeclaration8(%p)\n", This, pDeclaration8);
+
+  object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexShaderDeclarationImpl));
+  /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/
+  /*object->ref = 1;*/
+  object->device = This;
+  object->allFVF = 0;
+
+  while (D3DVSD_END() != *pToken) {
+    token = *pToken;
+    tokenlen = Direct3DVextexShaderDeclarationImpl_ParseToken(pToken); 
+    tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
+    
+    /** FVF generation block */
+    if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) {
+      /** 
+       * how really works streams, 
+       *  in DolphinVS dx8 dsk sample they seems to decal reg numbers !!!
+       */
+      DWORD oldStream = stream;
+      stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
+
+      /* copy fvf if valid */
+      if (FALSE == invalid_fvf) {
+          fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
+          tex = 0;
+          object->fvf[oldStream] = fvf;
+          object->allFVF |= fvf;
+      } else {
+          object->fvf[oldStream] = 0;
+          tex = 0;
+      }
+
+      /* reset valid/invalid fvf */
+      fvf = 0;
+      invalid_fvf = FALSE;
+
+    } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+
+      switch (reg) {
+      case D3DVSDE_POSITION:     
+	switch (type) {
+	case D3DVSDT_FLOAT3:     fvf |= D3DFVF_XYZ;             break;
+	case D3DVSDT_FLOAT4:     fvf |= D3DFVF_XYZRHW;          break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  if (type >= MAX_VSHADER_DECL_TYPES) {
+	    TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported and unrecognized type %08lx\n", type);
+	  } else {
+	    TRACE("Mismatched use in VertexShader declaration of D3DVSDE_POSITION register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	  }
+	}
+	break;
+      
+      case D3DVSDE_BLENDWEIGHT:
+	switch (type) {
+	case D3DVSDT_FLOAT1:     fvf |= D3DFVF_XYZB1;           break;
+	case D3DVSDT_FLOAT2:     fvf |= D3DFVF_XYZB2;           break;
+	case D3DVSDT_FLOAT3:     fvf |= D3DFVF_XYZB3;           break;
+	case D3DVSDT_FLOAT4:     fvf |= D3DFVF_XYZB4;           break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDWEIGHT register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break;
+
+      case D3DVSDE_BLENDINDICES: /* seem to be B5 as said in MSDN Dx9SDK ??  */
+	switch (type) {
+	case D3DVSDT_UBYTE4:     fvf |= D3DFVF_LASTBETA_UBYTE4;           break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_BLENDINDINCES register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break; 
+
+      case D3DVSDE_NORMAL: /* TODO: only FLOAT3 supported ... another choice possible ? */
+	switch (type) {
+	case D3DVSDT_FLOAT3:     fvf |= D3DFVF_NORMAL;          break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_NORMAL register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break; 
+
+      case D3DVSDE_PSIZE:  /* TODO: only FLOAT1 supported ... another choice possible ? */
+	switch (type) {
+        case D3DVSDT_FLOAT1:     fvf |= D3DFVF_PSIZE;           break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_PSIZE register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break;
+
+      case D3DVSDE_DIFFUSE:  /* TODO: only D3DCOLOR supported */
+	switch (type) {
+	case D3DVSDT_D3DCOLOR:   fvf |= D3DFVF_DIFFUSE;         break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_DIFFUSE register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break;
+
+      case D3DVSDE_SPECULAR:  /* TODO: only D3DCOLOR supported */
+	switch (type) {
+	case D3DVSDT_D3DCOLOR:	 fvf |= D3DFVF_SPECULAR;        break;
+	default: 
+	  /** errooooorr mismatched use of a register, invalid fvf computing */
+	  invalid_fvf = TRUE;
+	  TRACE("Mismatched use in VertexShader declaration of D3DVSDE_SPECULAR register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+	}
+	break;
+
+      case D3DVSDE_TEXCOORD0:
+      case D3DVSDE_TEXCOORD1:
+      case D3DVSDE_TEXCOORD2:
+      case D3DVSDE_TEXCOORD3:
+      case D3DVSDE_TEXCOORD4:
+      case D3DVSDE_TEXCOORD5:
+      case D3DVSDE_TEXCOORD6:
+      case D3DVSDE_TEXCOORD7:
+         /* Fixme? - assume all tex coords in same stream */
+         {
+             int texNo = 1 + (reg - D3DVSDE_TEXCOORD0);
+             tex = max(tex, texNo);
+             switch (type) {
+             case D3DVSDT_FLOAT1: fvf |= D3DFVF_TEXCOORDSIZE1(texNo); break;
+             case D3DVSDT_FLOAT2: fvf |= D3DFVF_TEXCOORDSIZE2(texNo); break;
+             case D3DVSDT_FLOAT3: fvf |= D3DFVF_TEXCOORDSIZE3(texNo); break;
+             case D3DVSDT_FLOAT4: fvf |= D3DFVF_TEXCOORDSIZE4(texNo); break;
+             default: 
+               /** errooooorr mismatched use of a register, invalid fvf computing */
+               invalid_fvf = TRUE;
+               TRACE("Mismatched use in VertexShader declaration of D3DVSDE_TEXCOORD? register: unsupported type %s\n", VertexShaderDeclDataTypes[type]);
+             }
+         }
+         break;
+
+      case D3DVSDE_POSITION2:   /* maybe D3DFVF_XYZRHW instead D3DFVF_XYZ (of D3DVDE_POSITION) ... to see */
+      case D3DVSDE_NORMAL2:     /* FIXME i don't know what to do here ;( */
+	TRACE("[%lu] registers in VertexShader declaration not supported yet (token:0x%08lx)\n", reg, token);
+	break;
+      }
+      TRACE("VertexShader declaration define %lx as current FVF\n", fvf);
+    }
+    len += tokenlen;
+    pToken += tokenlen;
+  }
+  /* here D3DVSD_END() */
+  len +=  Direct3DVextexShaderDeclarationImpl_ParseToken(pToken);
+
+  /* copy fvf if valid */
+  if (FALSE == invalid_fvf) {
+      fvf |= tex << D3DFVF_TEXCOUNT_SHIFT;
+      object->fvf[stream] = fvf;
+      object->allFVF |= fvf;
+  } else {
+      object->fvf[stream] = 0;
+  }
+  TRACE("Completed, allFVF = %lx\n", object->allFVF);
+
+  /* compute size */
+  object->declaration8Length = len * sizeof(DWORD);
+  /* copy the declaration */
+  object->pDeclaration8 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->declaration8Length);
+  memcpy(object->pDeclaration8, pDeclaration8, object->declaration8Length);
+  /* returns */
+  *ppVertexShaderDecl = object;
+  return D3D_OK;
+}
+
+
+HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDeviceImpl* This,
+							 IDirect3DVertexShaderImpl* vshader,	 
+							 DWORD SkipnStrides) {
+  /** parser data */
+  const DWORD* pToken = This->UpdateStateBlock->vertexShaderDecl->pDeclaration8;
+  DWORD stream = 0;
+  DWORD token;
+  /*DWORD tokenlen;*/
+  DWORD tokentype;
+  /** for input readers */
+  const char* curPos = NULL;
+  FLOAT x, y, z, w;
+  SHORT u, v, r, t;
+  DWORD dw;
+
+  TRACE("(%p) - This:%p, skipstrides=%lu\n", vshader, This, SkipnStrides);
+
+  while (D3DVSD_END() != *pToken) {
+    token = *pToken;
+    tokentype = ((token & D3DVSD_TOKENTYPEMASK) >> D3DVSD_TOKENTYPESHIFT);
+    
+    /** FVF generation block */
+    if (D3DVSD_TOKEN_STREAM == tokentype && 0 == (D3DVSD_STREAMTESSMASK & token)) {
+      IDirect3DVertexBufferImpl* pVB;
+      int skip = 0;
+
+      ++pToken;
+      /** 
+       * how really works streams, 
+       *  in DolphinVS dx8 dsk sample use it !!!
+       */
+      stream = ((token & D3DVSD_STREAMNUMBERMASK) >> D3DVSD_STREAMNUMBERSHIFT);
+      skip = This->StateBlock->stream_stride[stream];
+      pVB  = This->StateBlock->stream_source[stream];
+      
+      if (NULL == pVB) {
+	  ERR("using unitialised stream[%lu]\n", stream);
+	  return D3DERR_INVALIDCALL;
+      } else {
+          if (This->StateBlock->streamIsUP == TRUE) {
+              curPos = ((char *) pVB) + (SkipnStrides * skip);   /* Not really a VB */
+          } else {
+              curPos = ((IDirect3DVertexBufferImpl*) pVB)->allocatedMemory + (SkipnStrides * skip);
+          }
+	  
+	  TRACE(" using stream[%lu] with %p (%p + (Stride %d * skip %ld))\n", stream, curPos, 
+                 ((IDirect3DVertexBufferImpl*) pVB)->allocatedMemory, skip, SkipnStrides);
+      }
+    } else if (D3DVSD_TOKEN_CONSTMEM == tokentype) {
+      /** Const decl */
+      DWORD i;
+      DWORD count        = ((token & D3DVSD_CONSTCOUNTMASK)   >> D3DVSD_CONSTCOUNTSHIFT);
+      DWORD constaddress = ((token & D3DVSD_CONSTADDRESSMASK) >> D3DVSD_CONSTADDRESSSHIFT);
+      ++pToken;
+      for (i = 0; i < count; ++i) {
+	vshader->data->C[constaddress + i].x = *(float*)pToken;
+	vshader->data->C[constaddress + i].y = *(float*)(pToken + 1);
+	vshader->data->C[constaddress + i].z = *(float*)(pToken + 2);
+	vshader->data->C[constaddress + i].w = *(float*)(pToken + 3);
+	pToken += 4;
+      }
+
+    } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 != (0x10000000 & tokentype)) {
+      /** skip datas */
+      DWORD skipCount = ((token & D3DVSD_SKIPCOUNTMASK) >> D3DVSD_SKIPCOUNTSHIFT);
+      curPos = curPos + skipCount * sizeof(DWORD);
+      ++pToken;
+
+    } else if (D3DVSD_TOKEN_STREAMDATA == tokentype && 0 == (0x10000000 & tokentype)) {
+      DWORD type = ((token & D3DVSD_DATATYPEMASK)  >> D3DVSD_DATATYPESHIFT);
+      DWORD reg  = ((token & D3DVSD_VERTEXREGMASK) >> D3DVSD_VERTEXREGSHIFT);
+      ++pToken;
+
+      switch (type) {
+      case D3DVSDT_FLOAT1:
+	x = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	/**/
+	vshader->input.V[reg].x = x;
+	vshader->input.V[reg].y = 0.0f;
+	vshader->input.V[reg].z = 0.0f;
+	vshader->input.V[reg].w = 1.0f;
+	break;
+
+      case D3DVSDT_FLOAT2:
+	x = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	y = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	/**/
+	vshader->input.V[reg].x = x;
+	vshader->input.V[reg].y = y;
+	vshader->input.V[reg].z = 0.0f;
+	vshader->input.V[reg].w = 1.0f;
+	break;
+
+      case D3DVSDT_FLOAT3: 
+	x = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	y = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	z = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	/**/
+	vshader->input.V[reg].x = x;
+	vshader->input.V[reg].y = y;
+	vshader->input.V[reg].z = z;
+	vshader->input.V[reg].w = 1.0f;
+	break;
+
+      case D3DVSDT_FLOAT4: 
+	x = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	y = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	z = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	w = *(float*) curPos;
+	curPos = curPos + sizeof(float);
+	/**/
+	vshader->input.V[reg].x = x;
+	vshader->input.V[reg].y = y;
+	vshader->input.V[reg].z = z;
+	vshader->input.V[reg].w = w;
+	break;
+
+      case D3DVSDT_D3DCOLOR: 
+	dw = *(DWORD*) curPos;
+	curPos = curPos + sizeof(DWORD);
+	/**/
+	vshader->input.V[reg].x = (float) (((dw >> 16) & 0xFF) / 255.0f);
+	vshader->input.V[reg].y = (float) (((dw >>  8) & 0xFF) / 255.0f);
+	vshader->input.V[reg].z = (float) (((dw >>  0) & 0xFF) / 255.0f);
+	vshader->input.V[reg].w = (float) (((dw >> 24) & 0xFF) / 255.0f);
+	break;
+
+      case D3DVSDT_SHORT2: 
+	u = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	v = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	/**/
+	vshader->input.V[reg].x = (float) u;
+	vshader->input.V[reg].y = (float) v;
+	vshader->input.V[reg].z = 0.0f;
+	vshader->input.V[reg].w = 1.0f;
+	break;
+
+      case D3DVSDT_SHORT4: 
+	u = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	v = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	r = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	t = *(SHORT*) curPos;
+	curPos = curPos + sizeof(SHORT);
+	/**/
+	vshader->input.V[reg].x = (float) u;
+	vshader->input.V[reg].y = (float) v;
+	vshader->input.V[reg].z = (float) r;
+	vshader->input.V[reg].w = (float) t;
+	break;
+
+      case D3DVSDT_UBYTE4: 
+	dw = *(DWORD*) curPos;
+	curPos = curPos + sizeof(DWORD);
+	/**/
+	vshader->input.V[reg].x = (float) ((dw & 0x000F) >>  0);
+	vshader->input.V[reg].y = (float) ((dw & 0x00F0) >>  8);
+	vshader->input.V[reg].z = (float) ((dw & 0x0F00) >> 16);
+	vshader->input.V[reg].w = (float) ((dw & 0xF000) >> 24);
+	
+	break;
+
+      default: /** errooooorr what to do ? */
+	ERR("Error in VertexShader declaration of %s register: unsupported type %s\n", VertexShaderDeclRegister[reg], VertexShaderDeclDataTypes[type]);
+      }
+    }
+
+  }
+  /* here D3DVSD_END() */
+  return D3D_OK;
+}
+
+HRESULT WINAPI IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(IDirect3DVertexShaderDeclarationImpl* This, DWORD* pData, UINT* pSizeOfData) {
+  if (NULL == pData) {
+    *pSizeOfData = This->declaration8Length;
+    return D3D_OK;
+  }
+  if (*pSizeOfData < This->declaration8Length) {
+    *pSizeOfData = This->declaration8Length;
+    return D3DERR_MOREDATA;
+  }
+  TRACE("(%p) : GetVertexShaderDeclaration copying to %p\n", This, pData);
+  memcpy(pData, This->pDeclaration8, This->declaration8Length);
+  return D3D_OK;
+}
Les sous-répertoires /tmp/.wine-fenix et dlls/d3dcore/.wine-fenix sont identiques.
Les sous-répertoires /tmp/.wine-root et dlls/d3dcore/.wine-root sont identiques.
Les sous-répertoires /tmp/winetmp-fenix et dlls/d3dcore/winetmp-fenix sont identiques.
Les sous-répertoires /tmp/.X11-unix et dlls/d3dcore/.X11-unix sont identiques.


More information about the wine-patches mailing list