-----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-----
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 + +@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.