From c87fd95f1f91f16d341caa3cc85727eef31e8eeb Mon Sep 17 00:00:00 2001 From: Raphael Junqueira Date: Mon, 19 Apr 2004 23:04:58 +0000 Subject: [PATCH] - fix the SetTextureStageState for D3DTADDRESS_MIRROR using dynamic GL detection (and not build time GL headers) - add a new debug channel for hardware vertex shaders - hardware VS "compiler" fixes: -> special case for address registers (MOV must be replaced by ARL) -> add line numbers to trace (better to find why NVidia drivers complains) -> one parse to determine temporary and address registers needs (@todo: check GL limits) -> remove duplicate traces from Generic ParseProgram --- dlls/d3d8/d3d8_private.h | 2 + dlls/d3d8/d3dcore_gl.h | 9 ++- dlls/d3d8/device.c | 22 +++---- dlls/d3d8/directx.c | 16 +++++ dlls/d3d8/shader.c | 136 +++++++++++++++++++++++++++++---------- 5 files changed, 139 insertions(+), 46 deletions(-) diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index b0d3df10ab4..28b639f2698 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -2,6 +2,7 @@ * Direct3D 8 private include file * * Copyright 2002-2004 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or @@ -391,6 +392,7 @@ struct IDirect3DDevice8Impl GLint cursor; UINT dummyTextureName[8]; + }; /* IUnknown: */ diff --git a/dlls/d3d8/d3dcore_gl.h b/dlls/d3d8/d3dcore_gl.h index 0312273ea42..b29f5fb2550 100644 --- a/dlls/d3d8/d3dcore_gl.h +++ b/dlls/d3d8/d3dcore_gl.h @@ -1,7 +1,7 @@ /* * Direct3D gl definitions * - * Copyright 2003 Raphael Junqueira + * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or @@ -189,6 +189,11 @@ typedef void (APIENTRY * PGLFNGLPOINTPARAMETERFVEXTPROC) (GLenum pname, const GL #define GL_ARB_texture_border_clamp 1 #define GL_CLAMP_TO_BORDER_ARB 0x812D #endif +/* GL_ARB_texture_mirrored_repeat (full support GL1.4) */ +#ifndef GL_ARB_texture_mirrored_repeat +#define GL_ARB_texture_mirrored_repeat 1 +#define GL_MIRRORED_REPEAT_ARB 0x8370 +#endif /* GL_ATI_texture_mirror_once */ #ifndef GL_ATI_texture_mirror_once #define GL_ATI_texture_mirror_once 1 @@ -416,6 +421,7 @@ typedef enum _GL_SupportedExt { ARB_TEXTURE_ENV_COMBINE, ARB_TEXTURE_ENV_DOT3, ARB_TEXTURE_BORDER_CLAMP, + ARB_TEXTURE_MIRRORED_REPEAT, ARB_VERTEX_PROGRAM, ARB_VERTEX_BLEND, /* EXT */ @@ -550,6 +556,7 @@ typedef struct Direct3DVertexStridedData { #define USE_GL_FUNC(type, pfn) type pfn; typedef struct _GL_Info { + unsigned bIsFilled; /** * CAPS Constants */ diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index c1d3dcd5324..71fe98f3834 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -481,7 +481,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_ ICOM_THIS(IDirect3DDevice8Impl,iface); FIXME("(%p) : stub\n", This); return D3D_OK; } -HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) { +HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, + CONST RECT* pSourceRect, CONST RECT* pDestRect, + HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) { ICOM_THIS(IDirect3DDevice8Impl,iface); TRACE("(%p) : complete stub!\n", This); @@ -3454,15 +3456,13 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa break; case D3DTADDRESS_MIRROR: { -#if defined(GL_VERSION_1_4) - wrapParm = GL_MIRRORED_REPEAT; -#elif defined(GL_ARB_texture_mirrored_repeat) - wrapParm = GL_MIRRORED_REPEAT_ARB; -#else - /* Unsupported in OpenGL pre-1.4 */ - FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type); - wrapParm = GL_REPEAT; -#endif + if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) { + wrapParm = GL_MIRRORED_REPEAT_ARB; + } else { + /* Unsupported in OpenGL pre-1.4 */ + FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type); + wrapParm = GL_REPEAT; + } } break; case D3DTADDRESS_MIRRORONCE: @@ -3470,7 +3470,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 ifa if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) { wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI; } else { - FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type); + FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type); wrapParm = GL_REPEAT; } } diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index e266b8e9752..a7d1959618d 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -2,6 +2,7 @@ * IDirect3D8 implementation * * Copyright 2002-2004 Jason Edmeades + * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * * This library is free software; you can redistribute it and/or @@ -276,6 +277,15 @@ HRESULT WINAPI IDirect3D8Impl_CheckDeviceType (LPDIRECT3D8 iface, DisplayFormat, debug_d3dformat(DisplayFormat), BackBufferFormat, debug_d3dformat(BackBufferFormat), Windowed); + /* + switch (DisplayFormat) { + case D3DFMT_A8R8G8B8: + return D3DERR_NOTAVAILABLE; + default: + break; + } + */ + return D3D_OK; } @@ -707,6 +717,9 @@ static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) { GLint gl_max; ICOM_THIS(IDirect3D8Impl,iface); + if (This->gl_info.bIsFilled) return ; + This->gl_info.bIsFilled = 1; + /* * Initialize openGL extension related variables * with Default values @@ -782,6 +795,9 @@ static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) { } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) { FIXME(" FOUND: ARB Texture border clamp support\n"); This->gl_info.supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE; + } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) { + FIXME(" FOUND: ARB Texture mirrored repeat support\n"); + This->gl_info.supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE; } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) { This->gl_info.vs_arb_version = VS_VERSION_11; FIXME(" FOUND: ARB Vertex Shader support - version=%02x\n", This->gl_info.vs_arb_version); diff --git a/dlls/d3d8/shader.c b/dlls/d3d8/shader.c index 7039dbe38a0..9212fc73854 100644 --- a/dlls/d3d8/shader.c +++ b/dlls/d3d8/shader.c @@ -1,7 +1,7 @@ /* * shaders implementation * - * Copyright 2002 Raphael Junqueira + * Copyright 2002-2004 Raphael Junqueira * Copyright 2004 Jason Edmeades * Copyright 2004 Christian Costa * @@ -35,6 +35,7 @@ #include "d3d8_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); +WINE_DECLARE_DEBUG_CHANNEL(d3d_hw_shader); /* Shader debugging - Change the following line to enable debugging of software vertex shaders */ @@ -618,14 +619,67 @@ inline static VOID IDirect3DVertexShaderImpl_GenerateProgramArbHW(IDirect3DVerte const DWORD* pSavedToken = NULL; const SHADER_OPCODE* curOpcode = NULL; int nRemInstr = -1; - DWORD len = 0; DWORD i; + unsigned lineNum = 0; char *pgmStr = NULL; char tmpLine[255]; + DWORD nUseAddressRegister = 0; + DWORD nUseTempRegister = 0; + DWORD regtype; + DWORD reg; IDirect3DDevice8Impl* This = vshader->device; pgmStr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 65535); /* 64kb should be enough */ + /** + * First pass to determine what we need to declare: + * - Temporary variables + * - Adress variables + */ + if (NULL != pToken) { + while (D3DVS_END() != *pToken) { + if (vshader_is_version_token(*pToken)) { + /** skip version */ + ++pToken; + continue; + } + 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) { + while (*pToken & 0x80000000) { + /* skip unrecognized opcode */ + ++pToken; + } + } else { + if (curOpcode->num_params > 0) { + regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) << D3DSP_REGTYPE_SHIFT); + reg = ((*pToken) & 0x00001FFF); + /** we should validate GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR limits here */ + if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1; + /** we should validate GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB limits here */ + if (D3DSPR_TEMP == regtype && nUseTempRegister <= reg) nUseTempRegister = reg + 1; + ++pToken; + for (i = 1; i < curOpcode->num_params; ++i) { + regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) << D3DSP_REGTYPE_SHIFT); + reg = ((*pToken) & 0x00001FFF); + /** we should validate GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB limits here */ + if (D3DSPR_TEMP == regtype && nUseTempRegister <= reg) nUseTempRegister = reg + 1; + ++pToken; + } + } + } + } + } + + /** second pass, now generate */ + pToken = pFunction; + if (NULL != pToken) { while (D3DVS_END() != *pToken) { tmpLine[0] = 0; @@ -640,40 +694,47 @@ inline static VOID IDirect3DVertexShaderImpl_GenerateProgramArbHW(IDirect3DVerte int version = (((*pToken >> 8) & 0x0F) * 10) + (*pToken & 0x0F); int numTemps; - TRACE("vs.%lu.%lu;\n", (*pToken >> 8) & 0x0F, (*pToken & 0x0F)); + TRACE_(d3d_hw_shader)("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 */ + TRACE_(d3d_hw_shader)("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 */ + FIXME_(d3d_hw_shader)("No work done yet to support vs2.0 in hw\n"); + TRACE_(d3d_hw_shader)("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 */ + FIXME_(d3d_hw_shader)("No work done yet to support vs3.0 in hw\n"); + TRACE_(d3d_hw_shader)("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"); + FIXME_(d3d_hw_shader)("Unrecognized vertex shader version!\n"); } strcat(pgmStr,tmpLine); + ++lineNum; - for (i=0;iname); + /*TRACE("%s ", curOpcode->name);*/ /* Build opcode for GL vertex_program */ switch (curOpcode->opcode) { case D3DSIO_MOV: + { + if (0 < nUseAddressRegister) { + regtype = ((((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) << D3DSP_REGTYPE_SHIFT); + if (D3DSPR_ADDR == regtype) { + /** + * Raphael: + * NVidia drivers complains about MOV A0, T5.x; + * because we need to use ARL for address registers + */ + strcpy(tmpLine, "ARL"); + break; + } + } + } case D3DSIO_ADD: case D3DSIO_SUB: case D3DSIO_MAD: @@ -745,50 +817,46 @@ inline static VOID IDirect3DVertexShaderImpl_GenerateProgramArbHW(IDirect3DVerte continue; default: - FIXME("Cant handle opcode %s in hwShader\n", curOpcode->name); + FIXME_(d3d_hw_shader)("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(", "); + /*TRACE(", ");*/ strcat(tmpLine, ","); vshader_program_add_param(*pToken, 1, tmpLine); ++pToken; - ++len; } } - TRACE("\n"); + /*TRACE("\n");*/ strcat(tmpLine,";\n"); - TRACE("GL HW (%u) : %s", strlen(pgmStr), tmpLine); /* Dont add /n to this line as already in tmpLine */ + ++lineNum; + TRACE_(d3d_hw_shader)("GL HW (%u, %u) : %s", lineNum, 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 */ + ++lineNum; + TRACE_(d3d_hw_shader)("GL HW (%u, %u) : %s", lineNum, 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); + TRACE_(d3d_hw_shader)("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; + if (glGetError() == GL_INVALID_OPERATION) { + GLint errPos; + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos); + FIXME_(d3d_hw_shader)("HW VertexShader Error at position: %d\n%s\n", errPos, glGetString(GL_PROGRAM_ERROR_STRING_ARB)); + vshader->prgId = -1; } HeapFree(GetProcessHeap(), 0, pgmStr);