>From nobody Mon Sep 17 00:00:00 2001 From: Jason Green Date: Fri, 26 May 2006 01:46:29 -0400 To: wine-patches Subject: [PATCH 5/5] Add ability to store the GLSL Shader Program Object on the stateblock - When the app calls SetPixelShader or SetVertexShader, those functions will now either: - Create a new Program object and attach themselves to it, - or attach themselves to the existing object - Then, they will link into that object. - They will Detach old objects if necessary. --- dlls/wined3d/device.c | 82 ++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/stateblock.c | 14 +++++++ dlls/wined3d/wined3d_private.h | 3 + 3 files changed, 99 insertions(+), 0 deletions(-) c7bdccd97e7bd53a5b49bbce454c7628016b820b diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index eff9504..ff2b8c9 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -27,9 +27,11 @@ #include "config.h" #ifdef HAVE_FLOAT_H # include #endif +#include #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info /* x11drv GDI escapes */ @@ -4341,6 +4343,51 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetVer IWineD3DVertexShader_Release(oldShader); } + /* If we're using GLSL, we need to possibly create a Shader Program at this point, + * unless one is already set, then we need to attach the vertex shader object to it */ + if (NULL != pShader && wined3d_settings.shader_mode == SHADER_GLSL + && oldShader != pShader) { + + GLhandleARB programId = This->updateStateBlock->shaderPrgId; + GLhandleARB shaderObj = ((IWineD3DVertexShaderImpl*)pShader)->baseShader.prgId; + int success_flag = 0; + + if (programId == 0) { + /* No shader program is set, create a new program */ + programId = GL_EXTCALL(glCreateProgramObjectARB()); + TRACE_(d3d_shader)("Creating new shader program %u\n", programId); + + /* Store this programId on the stateblock */ + This->updateStateBlock->shaderPrgId = programId; + } else if (oldShader != NULL) { + /* Detach the old shader object */ + TRACE_(d3d_shader)("Detaching shader object %u from program %u\n", + ((IWineD3DVertexShaderImpl*)oldShader)->baseShader.prgId, programId); + GL_EXTCALL(glDetachObjectARB(programId, shaderObj)); + checkGLcall("glDetachObjectARB"); + } + + TRACE_(d3d_shader)("Attaching shader object %u to program %u\n", shaderObj, programId); + GL_EXTCALL(glAttachObjectARB(programId, shaderObj)); + checkGLcall("glAttachObjectARB"); + GL_EXTCALL(glLinkProgramARB(programId)); + GL_EXTCALL(glGetObjectParameterivARB(programId, + GL_OBJECT_LINK_STATUS_ARB, &success_flag)); + if (!success_flag) { + /* Print any linking errors in our shader */ + print_glsl_info_log(&GLINFO_LOCATION, programId); + } else { + /* Bind vertex attributes to a corresponding index number */ + int i; + char tmp_name[10]; + for (i = 0; i < 16; ++i) { + sprintf(tmp_name, "attrib%i", i); + glBindAttribLocationARB(programId, i, tmp_name); + } + checkGLcall("glBindAttribLocationARB"); + } + } + if (pShader != NULL && ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration != NULL) { TRACE("(%p) : setting vertexDeclaration(%p)\n", This, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration); IWineD3DDevice_SetVertexDeclaration(iface, ((IWineD3DVertexShaderImpl *)pShader)->vertexDeclaration); @@ -4522,6 +4569,41 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetPix IWineD3DPixelShader_Release(oldShader); } + /* If we're using GLSL, we need to possibly create a Shader Program at this point, + * unless one is already set, then we need to attach the pixel shader object to it */ + if (NULL != pShader && wined3d_settings.shader_mode == SHADER_GLSL) { + + GLhandleARB programId = This->updateStateBlock->shaderPrgId; + GLhandleARB shaderObj = ((IWineD3DPixelShaderImpl*)pShader)->baseShader.prgId; + int success_flag = 0; + + if (programId == 0) { + /* No shader program is set, create a new program */ + programId = GL_EXTCALL(glCreateProgramObjectARB()); + TRACE_(d3d_shader)("Creating new shader program %u\n", programId); + + /* Store this programId on the stateblock */ + This->updateStateBlock->shaderPrgId = programId; + } else if (oldShader != NULL) { + /* Detach the old shader object */ + TRACE_(d3d_shader)("Detaching shader object %u from program %u\n", + ((IWineD3DPixelShaderImpl*)oldShader)->baseShader.prgId, programId); + GL_EXTCALL(glDetachObjectARB(programId, shaderObj)); + checkGLcall("glDetachObjectARB"); + } + + TRACE_(d3d_shader)("Attaching shader object %u to program %u\n", shaderObj, programId); + GL_EXTCALL(glAttachObjectARB(programId, shaderObj)); + checkGLcall("glAttachObjectARB"); + GL_EXTCALL(glLinkProgramARB(programId)); + GL_EXTCALL(glGetObjectParameterivARB(programId, + GL_OBJECT_LINK_STATUS_ARB, &success_flag)); + if (!success_flag) { + /* Print any linking errors in our shader */ + print_glsl_info_log(&GLINFO_LOCATION, programId); + } + } + TRACE("(%p) : setting pShader(%p)\n", This, pShader); /** * TODO: merge HAL shaders context switching from prototype diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index af1a265..79e5a61 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -24,6 +24,7 @@ #include "config.h" #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->wineD3DDevice)->wineD3D))->gl_info /********************************************************** @@ -85,6 +86,14 @@ ULONG WINAPI IWineD3DStateBlockImpl_Rele IWineD3DVertexShader_Release(This->vertexShader); } + if ((NULL != This->pixelShader || NULL != This->vertexShader) && This->shaderPrgId != 0) { + ENTER_GL(); + TRACE_(d3d_shader)("Deleting GLSL shader program %u\n", This->shaderPrgId); + GL_EXTCALL(glDeleteObjectARB(This->shaderPrgId)); + checkGLcall("glDeleteObjectARB"); + LEAVE_GL(); + } + if (NULL != This->vertexDecl) { IWineD3DVertexDeclaration_Release(This->vertexDecl); } @@ -164,6 +173,7 @@ HRESULT WINAPI IWineD3DStateBlockImpl_Ca } This->vertexShader = targetStateBlock->vertexShader; + This->shaderPrgId = targetStateBlock->shaderPrgId; } /* Vertex Shader Constants */ @@ -228,6 +238,7 @@ HRESULT WINAPI IWineD3DStateBlockImpl_Ca } This->pixelShader = targetStateBlock->pixelShader; + This->shaderPrgId = targetStateBlock->shaderPrgId; } /* Pixel Shader Constants */ @@ -853,6 +864,9 @@ #endif } This->wineD3DDevice->currentPalette = 0; + /* Set default GLSL program ID to 0 */ + This->shaderPrgId = 0; + TRACE("-----------------------> Device defaults now set up...\n"); return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 3e3bf80..47b9583 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1071,6 +1071,9 @@ struct IWineD3DStateBlockImpl DWORD textureState[MAX_TEXTURES][WINED3D_HIGHEST_TEXTURE_STATE + 1]; /* Sampler States */ DWORD samplerState[MAX_SAMPLERS][WINED3D_HIGHEST_SAMPLER_STATE + 1]; + + /* GLSL Shader program ID */ + GLhandleARB shaderPrgId; }; -- 1.3.3