From 4f568633007fd349da3478b7308b560e6066dc54 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 15 Apr 2004 23:58:15 +0000 Subject: [PATCH] Authors: Jason Edmeades , Christian Costa Added support for vertex shader (using ARB_vertex_program extension). --- dlls/d3d8/Makefile.in | 2 +- dlls/d3d8/d3d8_main.c | 45 +++- dlls/d3d8/d3d8_private.h | 16 +- dlls/d3d8/d3dcore_gl.h | 155 +++++++++++++ dlls/d3d8/device.c | 5 +- dlls/d3d8/directx.c | 15 +- dlls/d3d8/drawprim.c | 149 +++++++++++- dlls/d3d8/shader.c | 407 +++++++++++++++++++++++++++++---- dlls/d3d8/vshaderdeclaration.c | 153 ++++++++++++- 9 files changed, 872 insertions(+), 75 deletions(-) diff --git a/dlls/d3d8/Makefile.in b/dlls/d3d8/Makefile.in index 9d379d805f0..fd77f859548 100644 --- a/dlls/d3d8/Makefile.in +++ b/dlls/d3d8/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = d3d8.dll -IMPORTS = user32 gdi32 kernel32 +IMPORTS = user32 gdi32 kernel32 advapi32 EXTRAINCL = @X_CFLAGS@ EXTRALIBS = -ldxguid -luuid @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@ @OPENGL_LIBS@ diff --git a/dlls/d3d8/d3d8_main.c b/dlls/d3d8/d3d8_main.c index c73b83823ff..9037cd482b5 100644 --- a/dlls/d3d8/d3d8_main.c +++ b/dlls/d3d8/d3d8_main.c @@ -22,6 +22,7 @@ #include "windef.h" #include "winbase.h" +#include "winreg.h" #include "wingdi.h" #include "winuser.h" #include "wine/debug.h" @@ -34,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); int num_lock = 0; void (*wine_tsx11_lock_ptr)(void) = NULL; void (*wine_tsx11_unlock_ptr)(void) = NULL; +int vs_mode; HRESULT WINAPI D3D8GetSWInfo(void) { @@ -64,18 +66,39 @@ IDirect3D8* WINAPI Direct3DCreate8(UINT SDKVersion) BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) { TRACE("D3D8 DLLMain Reason=%ld\n", fdwReason); - if (fdwReason == DLL_PROCESS_ATTACH) + if (fdwReason == DLL_PROCESS_ATTACH) + { + HMODULE mod; + char buffer[32]; + DWORD size = sizeof(buffer); + HKEY hkey = 0; + + DisableThreadLibraryCalls(hInstDLL); + + mod = GetModuleHandleA( "x11drv.dll" ); + if (mod) { - HMODULE mod; - - DisableThreadLibraryCalls(hInstDLL); - - 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" ); - } + wine_tsx11_lock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_lock" ); + wine_tsx11_unlock_ptr = (void *)GetProcAddress( mod, "wine_tsx11_unlock" ); } + if ( !RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\d3d", &hkey) && + !RegQueryValueExA( hkey, "vs_mode", 0, NULL, buffer, &size) ) + { + if (!strcmp(buffer,"none")) + { + TRACE("Disable vertex shader\n"); + vs_mode = VS_NONE; + } + else if (!strcmp(buffer,"emulation")) + { + TRACE("Force SW vertex shader\n"); + vs_mode = VS_SW; + } + else { + TRACE("Allow HW vertex shader\n"); + vs_mode = VS_HW; + } + } + } return TRUE; } diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 73d3cd574a0..b0d3df10ab4 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -1,7 +1,8 @@ /* * Direct3D 8 private include file * - * Copyright 2002 Jason Edmeades + * Copyright 2002-2004 Jason Edmeades + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,7 @@ /* THIS FILE MUST NOT CONTAIN X11 or MESA DEFINES */ #define XMD_H /* This is to prevent the Xmd.h inclusion bug :-/ */ #include +#define GLX_GLXEXT_PROTOTYPES #include #ifdef HAVE_GL_GLEXT_H # include @@ -64,6 +66,11 @@ extern int num_lock; #include "winbase.h" #include "d3d8.h" +extern int vs_mode; +#define VS_NONE 0 +#define VS_HW 1 +#define VS_SW 2 + /* Device caps */ #define MAX_PALETTES 256 #define MAX_STREAMS 16 @@ -1198,6 +1205,10 @@ struct IDirect3DVertexShaderImpl { UINT functionLength; DWORD usage; /* 0 || D3DUSAGE_SOFTWAREPROCESSING */ DWORD version; + + /** fields for hw vertex shader use */ + GLuint prgId; + /* run time datas */ VSHADERDATA8* data; VSHADERINPUTDATA8 input; @@ -1217,7 +1228,8 @@ extern DWORD WINAPI IDirect3DVertexShaderImpl_GetVersion(IDirect3DVertexShaderIm extern HRESULT WINAPI IDirect3DVertexShaderImpl_ExecuteSW(IDirect3DVertexShaderImpl* This, VSHADERINPUTDATA8* input, VSHADEROUTPUTDATA8* output); /* temporary internal Interfaces */ extern HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShader(IDirect3DDevice8Impl* This, CONST DWORD* pFunction, DWORD Usage, IDirect3DVertexShaderImpl** ppVertexShader); -extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* This, IDirect3DVertexShaderImpl* vshader, DWORD SkipnStrides); +extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputSW(IDirect3DDevice8Impl* This, IDirect3DVertexShaderImpl* vshader, DWORD SkipnStrides); +extern HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputArbHW(IDirect3DDevice8Impl* This, IDirect3DVertexShaderImpl* vshader, DWORD SkipnStrides); /* ------------------------ */ /* IDirect3DPixelShaderImpl */ diff --git a/dlls/d3d8/d3dcore_gl.h b/dlls/d3d8/d3dcore_gl.h index dbe50b8266f..0312273ea42 100644 --- a/dlls/d3d8/d3dcore_gl.h +++ b/dlls/d3d8/d3dcore_gl.h @@ -2,6 +2,7 @@ * Direct3D gl definitions * * Copyright 2003 Raphael Junqueira + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -206,6 +207,151 @@ typedef void (APIENTRY * PGLFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GL #define GL_DOT3_RGB_EXT 0x8740 #define GL_DOT3_RGBA_EXT 0x8741 #endif +/* GL_ARB_vertex_program */ +#ifndef GL_ARB_vertex_program +#define GL_ARB_vertex_program 1 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DARBPROC) (GLuint index, GLdouble x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FARBPROC) (GLuint index, GLfloat x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SARBPROC) (GLuint index, GLshort x); +typedef void (APIENTRY * PFNGLVERTEXATTRIB1SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DARBPROC) (GLuint index, GLdouble x, GLdouble y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FARBPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SARBPROC) (GLuint index, GLshort x, GLshort y); +typedef void (APIENTRY * PFNGLVERTEXATTRIB2SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (APIENTRY * PFNGLVERTEXATTRIB3SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NBVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NIVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NSVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUBARBPROC) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4NUSVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4BVARBPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DARBPROC) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4DVARBPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FARBPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4FVARBPROC) (GLuint index, const GLfloat *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4IVARBPROC) (GLuint index, const GLint *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SARBPROC) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4SVARBPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UBVARBPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4UIVARBPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIB4USVARBPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRY * PFNGLVERTEXATTRIBPOINTERARBPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (APIENTRY * PFNGLENABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRY * PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) (GLuint index); +typedef void (APIENTRY * PFNGLPROGRAMSTRINGARBPROC) (GLenum target, GLenum format, GLsizei len, const GLvoid *string); +typedef void (APIENTRY * PFNGLBINDPROGRAMARBPROC) (GLenum target, GLuint program); +typedef void (APIENTRY * PFNGLDELETEPROGRAMSARBPROC) (GLsizei n, const GLuint *programs); +typedef void (APIENTRY * PFNGLGENPROGRAMSARBPROC) (GLsizei n, GLuint *programs); +typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLPROGRAMENVPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DARBPROC) (GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) (GLenum target, GLuint index, const GLdouble *params); +typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FARBPROC) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (APIENTRY * PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) (GLenum target, GLuint index, const GLfloat *params); +typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRY * PFNGLGETPROGRAMENVPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) (GLenum target, GLuint index, GLdouble *params); +typedef void (APIENTRY * PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) (GLenum target, GLuint index, GLfloat *params); +typedef void (APIENTRY * PFNGLGETPROGRAMIVARBPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETPROGRAMSTRINGARBPROC) (GLenum target, GLenum pname, GLvoid *string); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBDVARBPROC) (GLuint index, GLenum pname, GLdouble *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBFVARBPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBIVARBPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRY * PFNGLGETVERTEXATTRIBPOINTERVARBPROC) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef GLboolean (APIENTRY * PFNGLISPROGRAMARBPROC) (GLuint program); +#endif /******* * OpenGL Official Version @@ -334,6 +480,15 @@ typedef enum _GL_PSVersion { USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FEXTPROC, glSecondaryColor3fEXT); \ USE_GL_FUNC(PGLFNGLSECONDARYCOLOR3FVEXTPROC, glSecondaryColor3fvEXT); \ USE_GL_FUNC(PGLFNGLSECONDARYCOLORPOINTEREXTPROC, glSecondaryColorPointerEXT); \ + /* GL_EXT_secondary_color */ \ + USE_GL_FUNC(PFNGLGENPROGRAMSARBPROC, glGenProgramsARB); \ + USE_GL_FUNC(PFNGLBINDPROGRAMARBPROC, glBindProgramARB); \ + USE_GL_FUNC(PFNGLPROGRAMSTRINGARBPROC, glProgramStringARB); \ + USE_GL_FUNC(PFNGLDELETEPROGRAMSARBPROC, glDeleteProgramsARB); \ + USE_GL_FUNC(PFNGLPROGRAMENVPARAMETER4FVARBPROC, glProgramEnvParameter4fvARB); \ + USE_GL_FUNC(PFNGLVERTEXATTRIBPOINTERARBPROC, glVertexAttribPointerARB); \ + USE_GL_FUNC(PFNGLENABLEVERTEXATTRIBARRAYARBPROC, glEnableVertexAttribArrayARB); \ + USE_GL_FUNC(PFNGLDISABLEVERTEXATTRIBARRAYARBPROC, glDisableVertexAttribArrayARB); \ #define GLX_EXT_FUNCS_GEN \ /** GLX_VERSION_1_3 **/ \ diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 9ddc4f6eb86..c1d3dcd5324 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1248,7 +1248,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, I return D3D_OK; } - TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil); + FIXME("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil); hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil); @@ -3920,6 +3920,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object); /* TODO: check validity of object */ if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function); + if (object->prgId != 0) { + GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId )); + } HeapFree(GetProcessHeap(), 0, (void *)object->data); HeapFree(GetProcessHeap(), 0, (void *)object); VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL; diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index 8768a3dfcd2..e266b8e9752 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -1,7 +1,8 @@ /* * IDirect3D8 implementation * - * Copyright 2002 Jason Edmeades + * Copyright 2002-2004 Jason Edmeades + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -313,6 +314,7 @@ HRESULT WINAPI IDirect3D8Impl_CheckDeviceFormat (LPDIRECT3D8 iface, case D3DFMT_X8L8V8U8: case D3DFMT_L6V5U5: case D3DFMT_V8U8: + case D3DFMT_L8: /* Since we do not support these formats right now, don't pretend to. */ return D3DERR_NOTAVAILABLE; default: @@ -646,6 +648,7 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D #if defined(GL_EXT_texture_filter_anisotropic) glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max); + checkGLcall("glGetInterv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT)"); pCaps->MaxAnisotropy = gl_max; #else pCaps->MaxAnisotropy = 0; @@ -668,13 +671,11 @@ HRESULT WINAPI IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D pCaps->MaxStreams = MAX_STREAMS; pCaps->MaxStreamStride = 1024; -#if 1 - pCaps->VertexShaderVersion = D3DVS_VERSION(1,1); + if (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) || (vs_mode == VS_SW) || (DeviceType == D3DDEVTYPE_REF)) + pCaps->VertexShaderVersion = D3DVS_VERSION(1,1); + else + pCaps->VertexShaderVersion = 0; pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS; -#else - pCaps->VertexShaderVersion = 0; - pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS; -#endif #if 0 pCaps->PixelShaderVersion = D3DPS_VERSION(1,1); diff --git a/dlls/d3d8/drawprim.c b/dlls/d3d8/drawprim.c index 1afff076fd7..d98a6a4bd18 100644 --- a/dlls/d3d8/drawprim.c +++ b/dlls/d3d8/drawprim.c @@ -1,8 +1,9 @@ /* * D3D8 utils * - * Copyright 2002-2003 Jason Edmeades - * Raphael Junqueira + * Copyright 2002-2004 Jason Edmeades + * Copyright 2002-2004 Raphael Junqueira + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -831,18 +832,30 @@ void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, if (!GL_SUPPORT(ARB_MULTITEXTURE) && textureNo > 0) { FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n"); glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#if defined(GL_VERSION_1_3) + glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1); +#else glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1); +#endif continue; } if (coordIdx > 7) { VTRACE(("tex: %d - Skip tex coords, as being system generated\n", textureNo)); glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#if defined(GL_VERSION_1_3) + glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1); +#else glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1); +#endif } else if (sd->u.s.texCoords[coordIdx].lpData == NULL) { VTRACE(("Bound texture but no texture coordinates supplied, so skipping\n")); glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#if defined(GL_VERSION_1_3) + glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1); +#else glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1); +#endif } else { /* The coords to supply depend completely on the fvf / vertex shader */ @@ -866,7 +879,11 @@ void drawStridedFast(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, } } else { glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#if defined(GL_VERSION_1_3) + glMultiTexCoord4f(GL_TEXTURE0 + textureNo, 0, 0, 0, 1); +#else glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1); +#endif } } @@ -1280,7 +1297,7 @@ void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *s } /* Fill the vertex shader input */ - IDirect3DDeviceImpl_FillVertexShaderInput(This, vertex_shader, SkipnStrides); + IDirect3DDeviceImpl_FillVertexShaderInputSW(This, vertex_shader, SkipnStrides); /* Initialize the output fields to the same defaults as it would normally have */ memset(&vertex_shader->output, 0, sizeof(VSHADEROUTPUTDATA8)); @@ -1360,6 +1377,86 @@ void drawStridedSoftwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *s checkGLcall("glEnd and previous calls"); } +void drawStridedHardwareVS(LPDIRECT3DDEVICE8 iface, Direct3DVertexStridedData *sd, + int PrimitiveType, ULONG NumPrimitives, + const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx) { + + IDirect3DVertexShaderImpl* vertex_shader = NULL; + int i; + int NumVertexes; + int glPrimType; + int maxAttribs; + + ICOM_THIS(IDirect3DDevice8Impl,iface); + TRACE("Drawing with hardware vertex shaders\n"); + + /* Retrieve the VS information */ + vertex_shader = VERTEX_SHADER(This->StateBlock->VertexShader); + + /* Enable the Vertex Shader */ + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId)); + checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertex_shader->prgId);"); + glEnable(GL_VERTEX_PROGRAM_ARB); + checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);"); + + /* Update the constants */ + for (i=0; iStateBlock->vertexShaderConstant[i])); + checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB"); + } + + /* Set up the vertex.attr[n] inputs */ + IDirect3DDeviceImpl_FillVertexShaderInputArbHW(This, vertex_shader, 0); + + /* 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 1 /* FIXME: Want to use DrawRangeElements, but wrong calculation! */ + glDrawElements(glPrimType, NumVertexes, idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, + (char *)idxData+(idxSize * startIdx)); +#else + glDrawRangeElements(glPrimType, minIndex, minIndex+NumVertexes-1, NumVertexes, + idxSize==2?GL_UNSIGNED_SHORT:GL_UNSIGNED_INT, + (char *)idxData+(idxSize * 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"); + + } + + { + GLint errPos; + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); + if (errPos != -1) + FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) ); + } + + + /* Leave all the attribs disabled */ + glGetIntegerv( GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs); + /* MESA does not support it right not */ + if (glGetError() != GL_NO_ERROR) + maxAttribs = 16; + for (i=0; iUpdateStateBlock->VertexShader); memset(&vertex_shader->input, 0, sizeof(VSHADERINPUTDATA8)); + useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) && + This->devType != D3DDEVTYPE_REF && + !This->StateBlock->renderstate[D3DRS_SOFTWAREVERTEXPROCESSING] && + vertex_shader->usage != D3DUSAGE_SOFTWAREPROCESSING); + /** init Constants */ if (TRUE == This->UpdateStateBlock->Changed.vertexShaderConstant) { TRACE_(d3d_shader)("vertex shader initializing constants\n"); @@ -1400,10 +1503,18 @@ void drawPrimitive(LPDIRECT3DDEVICE8 iface, ENTER_GL(); /* Setup transform matrices and sort out */ - isLightingOn = primitiveInitState(iface, - fvf & D3DFVF_XYZRHW, - !(fvf & D3DFVF_NORMAL), - useVertexShaderFunction); + if (useHW) { + /* Lighting is not completely bypassed with ATI drivers although it should be. Mesa is ok from this respect... + So make sure lighting is disabled. */ + isLightingOn = glIsEnabled(GL_LIGHTING); + glDisable(GL_LIGHTING); + checkGLcall("glDisable(GL_LIGHTING);"); + TRACE("Disabled lighting as no normals supplied, old state = %d\n", isLightingOn); + } else + isLightingOn = primitiveInitState(iface, + fvf & D3DFVF_XYZRHW, + !(fvf & D3DFVF_NORMAL), + useVertexShaderFunction); /* Initialize all values to null */ if (useVertexShaderFunction == FALSE) { @@ -1434,15 +1545,33 @@ void drawPrimitive(LPDIRECT3DDEVICE8 iface, /* Now initialize the materials state */ init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL)); + /* And re-upload any dirty textures */ + for (i=0; iStateBlock->textures[i] != NULL) && + (IDirect3DBaseTexture8Impl_IsDirty(This->StateBlock->textures[i]))) + { + /* Load up the texture now */ + IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) This->StateBlock->textures[i]); + } + } + /* 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(iface, &dataLocations, PrimitiveType, NumPrimitives, + if (useHW) { + TRACE("Swap HW vertex shader\n"); + drawStridedHardwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, idxData, idxSize, minIndex, StartIdx); + } else { + /* We will have to use the very, very slow emulation layer */ + TRACE("Swap SW vertex shader\n"); + drawStridedSoftwareVS(iface, &dataLocations, PrimitiveType, NumPrimitives, + idxData, idxSize, minIndex, StartIdx); + } } else if ((dataLocations.u.s.pSize.lpData != NULL) || (dataLocations.u.s.diffuse.lpData != NULL) || diff --git a/dlls/d3d8/shader.c b/dlls/d3d8/shader.c index 867e66250e7..7039dbe38a0 100644 --- a/dlls/d3d8/shader.c +++ b/dlls/d3d8/shader.c @@ -2,6 +2,8 @@ * shaders implementation * * Copyright 2002 Raphael Junqueira + * Copyright 2004 Jason Edmeades + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +24,7 @@ #include #include +#include #include "windef.h" #include "winbase.h" @@ -43,7 +46,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); # define TRACE_VSVECTOR(name) #endif - /** * DirectX9 SDK download * http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp @@ -346,36 +348,37 @@ void vshader_lrp(D3DSHADERVECTOR* d, D3DSHADERVECTOR* s0, D3DSHADERVECTOR* s1, D /** * log, exp, frc, m*x* seems to be macros ins ... to see + * Note opcode must be in uppercase if direct mapping to GL hw shaders */ 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}, + {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}, + {D3DSIO_EXPP, "EXPP", 2, vshader_expp, 0, 0}, + {D3DSIO_LOGP, "LOGP", 2, vshader_logp, 0, 0}, {0, NULL, 0, NULL, 0, 0} }; @@ -393,6 +396,14 @@ inline static const SHADER_OPCODE* vshader_program_get_opcode(const DWORD code) return NULL; } +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); +} + 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"; @@ -463,18 +474,327 @@ inline static void vshader_program_dump_param(const DWORD param, int input) { } } -inline static BOOL vshader_is_version_token(DWORD token) { - return 0xFFFE0000 == (token & 0xFFFE0000); +inline static void vshader_program_add_param(const DWORD param, int input, char *hwLine) { + /*static const char* rastout_reg_names[] = { "oPos", "oFog", "oPts" }; */ + static const char* hwrastout_reg_names[] = { "result.position", "result.fogcoord", "result.pointsize" }; + static const char swizzle_reg_chars[] = "xyzw"; + + DWORD reg = param & 0x00001FFF; + DWORD regtype = ((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT); + char tmpReg[255]; + + if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NEG) { + strcat(hwLine, " -"); + } else { + strcat(hwLine, " "); + } + + switch (regtype << D3DSP_REGTYPE_SHIFT) { + case D3DSPR_TEMP: + sprintf(tmpReg, "T%lu", reg); + strcat(hwLine, tmpReg); + break; + case D3DSPR_INPUT: + sprintf(tmpReg, "vertex.attrib[%lu]", reg); + strcat(hwLine, tmpReg); + break; + case D3DSPR_CONST: + sprintf(tmpReg, "program.env[%lu]", reg); + strcat(hwLine, tmpReg); + break; + case D3DSPR_ADDR: /*case D3DSPR_TEXTURE:*/ + sprintf(tmpReg, "A%lu", reg); + strcat(hwLine, tmpReg); + break; + case D3DSPR_RASTOUT: + sprintf(tmpReg, "%s", hwrastout_reg_names[reg]); + strcat(hwLine, tmpReg); + break; + case D3DSPR_ATTROUT: + if (reg==0) { + strcat(hwLine, "result.color.primary"); + } else { + strcat(hwLine, "result.color.secondary"); + } + break; + case D3DSPR_TEXCRDOUT: + sprintf(tmpReg, "result.texcoord[%lu]", reg); + strcat(hwLine, tmpReg); + break; + default: + break; + } + + if (!input) { + /** operand output */ + if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) { + strcat(hwLine, "."); + if (param & D3DSP_WRITEMASK_0) { + strcat(hwLine, "x"); + } + if (param & D3DSP_WRITEMASK_1) { + strcat(hwLine, "y"); + } + if (param & D3DSP_WRITEMASK_2) { + strcat(hwLine, "z"); + } + if (param & D3DSP_WRITEMASK_3) { + strcat(hwLine, "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) { + sprintf(tmpReg, ".%c", swizzle_reg_chars[swizzle_x]); + strcat(hwLine, tmpReg); + } else { + sprintf(tmpReg, ".%c%c%c%c", + swizzle_reg_chars[swizzle_x], + swizzle_reg_chars[swizzle_y], + swizzle_reg_chars[swizzle_z], + swizzle_reg_chars[swizzle_w]); + strcat(hwLine, tmpReg); + } + } + } } -inline static BOOL vshader_is_comment_token(DWORD token) { - return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK); -} +DWORD MacroExpansion[4*4]; + +int ExpandMxMacro(DWORD macro_opcode, const DWORD* args) { + int i; + int nComponents = 0; + DWORD opcode =0; + switch(macro_opcode) { + case D3DSIO_M4x4: + nComponents = 4; + opcode = D3DSIO_DP4; + break; + case D3DSIO_M4x3: + nComponents = 3; + opcode = D3DSIO_DP4; + break; + case D3DSIO_M3x4: + nComponents = 4; + opcode = D3DSIO_DP3; + break; + case D3DSIO_M3x3: + nComponents = 3; + opcode = D3DSIO_DP3; + break; + case D3DSIO_M3x2: + nComponents = 2; + opcode = D3DSIO_DP3; + break; + default: + break; + } + for (i = 0; i < nComponents; i++) { + MacroExpansion[i*4+0] = opcode; + MacroExpansion[i*4+1] = ((*args) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<device; + + pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */ + + if (NULL != pToken) { + while (D3DVS_END() != *pToken) { + tmpLine[0] = 0; + + if ((nRemInstr >= 0) && (--nRemInstr == -1)) + /* Macro is finished, continue normal path */ + pToken = pSavedToken; + + if (vshader_is_version_token(*pToken)) { /** version */ + + /* Extract version *10 into integer value (ie. 1.0 == 10, 1.1==11 etc */ + int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F); + int numTemps; + + TRACE("vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F)); + + /* Each release of vertex shaders has had different numbers of temp registers */ + switch (version) { + case 10: + case 11: numTemps=12; + strcpy(tmpLine, "!!ARBvp1.0\n"); + TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + break; + case 20: numTemps=12; + strcpy(tmpLine, "!!ARBvp2.0\n"); + FIXME("No work done yet to support vs2.0 in hw\n"); + TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + break; + case 30: numTemps=32; + strcpy(tmpLine, "!!ARBvp3.0\n"); + FIXME("No work done yet to support vs3.0 in hw\n"); + TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + break; + default: + numTemps=12; + strcpy(tmpLine, "!!ARBvp1.0\n"); + FIXME("Unrecognized vertex shader version!\n"); + } + strcat(pgmStr,tmpLine); + + for (i=0;i> 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); + + /* Build opcode for GL vertex_program */ + switch (curOpcode->opcode) { + case D3DSIO_MOV: + case D3DSIO_ADD: + case D3DSIO_SUB: + case D3DSIO_MAD: + case D3DSIO_MUL: + case D3DSIO_RCP: + case D3DSIO_RSQ: + case D3DSIO_DP3: + case D3DSIO_DP4: + case D3DSIO_MIN: + case D3DSIO_MAX: + case D3DSIO_SLT: + case D3DSIO_SGE: + case D3DSIO_LIT: + case D3DSIO_DST: + case D3DSIO_FRC: + strcpy(tmpLine, curOpcode->name); + break; + + case D3DSIO_EXPP: + strcpy(tmpLine, "EXP"); + break; + case D3DSIO_LOGP: + strcpy(tmpLine, "LOG"); + break; + case D3DSIO_EXP: + strcpy(tmpLine, "EX2"); + break; + case D3DSIO_LOG: + strcpy(tmpLine, "LG2"); + break; + + case D3DSIO_M4x4: + case D3DSIO_M4x3: + case D3DSIO_M3x4: + case D3DSIO_M3x3: + case D3DSIO_M3x2: + /* Expand the macro and get number of generated instruction */ + nRemInstr = ExpandMxMacro(curOpcode->opcode, pToken); + /* Save point to next instruction */ + pSavedToken = pToken + 3; + /* Execute expanded macro */ + pToken = MacroExpansion; + continue; + + default: + FIXME("Cant handle opcode %s in hwShader\n", curOpcode->name); + } + + if (curOpcode->num_params > 0) { + vshader_program_add_param(*pToken, 0, tmpLine); + + ++pToken; + ++len; + for (i = 1; i < curOpcode->num_params; ++i) { + TRACE(", "); + strcat(tmpLine, ","); + vshader_program_add_param(*pToken, 1, tmpLine); + ++pToken; + ++len; + } + } + TRACE("\n"); + strcat(tmpLine,";\n"); + TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + strcat(pgmStr, tmpLine); + } + } + vshader->functionLength = (len + 1) * sizeof(DWORD); + strcpy(tmpLine, "END\n"); + TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + strcat(pgmStr, tmpLine); + } else { + vshader->functionLength = 1; /* no Function defined use fixed function vertex processing */ + } + + + /* Create the hw shader */ + GL_EXTCALL(glGenProgramsARB(1, &vshader->prgId)); + TRACE("Creating a hw vertex shader, prg=%d\n", vshader->prgId); + + GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vshader->prgId)); + + /* Create the program and check for errors */ + GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(pgmStr), pgmStr)); + if ( glGetError() == GL_INVALID_OPERATION) { + GLint errPos; + glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos ); + FIXME("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString( GL_PROGRAM_ERROR_STRING_ARB) ); + vshader->prgId = -1; + } + + HeapFree(GetProcessHeap(), 0, pgmStr); +} + +inline static VOID IDirect3DVertexShaderImpl_ParseProgram(IDirect3DVertexShaderImpl* vshader, CONST DWORD* pFunction, int useHW) { const DWORD* pToken = pFunction; const SHADER_OPCODE* curOpcode = NULL; DWORD len = 0; @@ -526,8 +846,12 @@ inline static VOID IDirect3DVertexShaderImpl_ParseProgram(IDirect3DVertexShaderI } else { vshader->functionLength = 1; /* no Function defined use fixed function vertex processing */ } - /* copy the function ... because it will certainly be released by application */ + /* Generate HW shader in needed */ + if (useHW) + IDirect3DVertexShaderImpl_GenerateProgramArbHW(vshader, pFunction); + + /* 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); @@ -538,7 +862,8 @@ inline static VOID IDirect3DVertexShaderImpl_ParseProgram(IDirect3DVertexShaderI HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShader(IDirect3DDevice8Impl* This, CONST DWORD* pFunction, DWORD Usage, IDirect3DVertexShaderImpl** ppVertexShader) { IDirect3DVertexShaderImpl* object; - + int useHW; + object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexShaderImpl)); if (NULL == object) { *ppVertexShader = NULL; @@ -550,8 +875,12 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShader(IDirect3DDevice8Impl* This object->usage = Usage; object->data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VSHADERDATA8)); - - IDirect3DVertexShaderImpl_ParseProgram(object, pFunction); + + useHW = (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) && + This->devType != D3DDEVTYPE_REF && + object->usage != D3DUSAGE_SOFTWAREPROCESSING); + + IDirect3DVertexShaderImpl_ParseProgram(object, pFunction, useHW); *ppVertexShader = object; return D3D_OK; @@ -633,7 +962,7 @@ HRESULT WINAPI IDirect3DVertexShaderImpl_ExecuteSW(IDirect3DVertexShaderImpl* vs 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); + vshader_program_add_param(*pToken, i, NULL); /* Add function just used for trace error scenario */ TRACE("\n"); ++i; ++pToken; diff --git a/dlls/d3d8/vshaderdeclaration.c b/dlls/d3d8/vshaderdeclaration.c index 2dc73ec2789..00389e6b7c1 100644 --- a/dlls/d3d8/vshaderdeclaration.c +++ b/dlls/d3d8/vshaderdeclaration.c @@ -2,6 +2,8 @@ * vertex shaders declaration implementation * * Copyright 2002 Raphael Junqueira + * Copyright 2004 Jason Edmeades + * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -201,6 +203,7 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(IDirect3DDevic TRACE("(%p) : pDeclaration8(%p)\n", This, pDeclaration8); object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexShaderDeclarationImpl)); + /*object->lpVtbl = &Direct3DVextexShaderDeclaration8_Vtbl;*/ object->device = This; /* FIXME: AddRef(This) */ object->ref = 1; @@ -376,10 +379,9 @@ HRESULT WINAPI IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(IDirect3DDevic return D3D_OK; } - -HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* This, - IDirect3DVertexShaderImpl* vshader, - DWORD SkipnStrides) { +HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputSW(IDirect3DDevice8Impl* This, + IDirect3DVertexShaderImpl* vshader, + DWORD SkipnStrides) { /** parser data */ const DWORD* pToken = This->UpdateStateBlock->vertexShaderDecl->pDeclaration8; DWORD stream = 0; @@ -564,6 +566,149 @@ HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInput(IDirect3DDevice8Impl* T return D3D_OK; } +HRESULT WINAPI IDirect3DDeviceImpl_FillVertexShaderInputArbHW(IDirect3DDevice8Impl* 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; + int skip = 0; + + 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)) { + IDirect3DVertexBuffer8* pVB; + + ++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 = ((IDirect3DVertexBuffer8Impl*) pVB)->allocatedMemory + (SkipnStrides * skip); + } + + TRACE(" using stream[%lu] with %p (%p + (Stride %d * skip %ld))\n", stream, curPos, + ((IDirect3DVertexBuffer8Impl*) 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) { + FIXME("Confirm this is correct handling of consts inside the hw vertex shader\n"); + GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, constaddress+i, (GLfloat *)pToken)); + 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); + TRACE(" skipping %ld dwords\n", skipCount); + 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; + + TRACE(" type : %ld, reg = %ld\n", type, reg); + switch (type) { + case D3DVSDT_FLOAT1: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 1, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 1, GL_FLOAT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + sizeof(float); + break; + + case D3DVSDT_FLOAT2: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 2, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 2, GL_FLOAT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 2*sizeof(float); + break; + + case D3DVSDT_FLOAT3: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 3, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 3, GL_FLOAT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 3*sizeof(float); + break; + + case D3DVSDT_FLOAT4: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 4, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_FLOAT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 4*sizeof(float); + break; + + case D3DVSDT_D3DCOLOR: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 4, skip, curPos); + FIXME("D3DVSDT_D3DCOLOR in hw shader - To confirm\n"); + GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_BYTE, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 4*sizeof(BYTE); + break; + + case D3DVSDT_SHORT2: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 2, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 2, GL_UNSIGNED_SHORT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 2*sizeof(short int); + break; + + case D3DVSDT_SHORT4: + TRACE("HW VS glVertexAttribPointerARB(reg=%ld,num=%d,skip=%d,ptr=%p)\n", reg, 1, skip, curPos); + GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_SHORT, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 4*sizeof(short int); + break; + + case D3DVSDT_UBYTE4: + FIXME("D3DVSDT_UBYTE4 in hw shader - To confirm\n"); + GL_EXTCALL(glVertexAttribPointerARB(reg, 4, GL_UNSIGNED_BYTE, GL_FALSE, skip, curPos)); + GL_EXTCALL(glEnableVertexAttribArrayARB(reg)); + curPos = curPos + 4*sizeof(BYTE); + 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;