From c9723510513bea1e0b73668af1d9e8fc8a806144 Mon Sep 17 00:00:00 2001 From: "H. Verbeet" Date: Thu, 28 Dec 2006 03:13:24 +0100 Subject: [PATCH] wined3d: Move set_glsl_shader_program() to glsl_shader.c. --- dlls/wined3d/device.c | 117 --------------------------------- dlls/wined3d/glsl_shader.c | 117 +++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d_private.h | 1 - 3 files changed, 117 insertions(+), 118 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 14d6d9eb479..4ebca233541 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -251,123 +251,6 @@ static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightIn * GLSL helper functions follow **********************************************************/ -/** Attach a GLSL pixel or vertex shader object to the shader program */ -static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) { - - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId; - if (This->stateBlock->glsl_program && shaderObj != 0) { - TRACE_(d3d_shader)("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId); - GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj)); - checkGLcall("glAttachObjectARB"); - } -} - -/** Sets the GLSL program ID for the given pixel and vertex shader combination. - * It sets the programId on the current StateBlock (because it should be called - * inside of the DrawPrimitive() part of the render loop). - * - * If a program for the given combination does not exist, create one, and store - * the program in the list. If it creates a program, it will link the given - * objects, too. - * - * We keep the shader programs around on a list because linking - * shader objects together is an expensive operation. It's much - * faster to loop through a list of pre-compiled & linked programs - * each time that the application sets a new pixel or vertex shader - * than it is to re-link them together at that time. - * - * The list will be deleted in IWineD3DDevice::Release(). - */ -void set_glsl_shader_program(IWineD3DDevice *iface) { - - IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; - IWineD3DPixelShader *pshader = This->stateBlock->pixelShader; - IWineD3DVertexShader *vshader = This->stateBlock->vertexShader; - struct glsl_shader_prog_link *curLink = NULL; - struct glsl_shader_prog_link *newLink = NULL; - struct list *ptr = NULL; - GLhandleARB programId = 0; - int i; - char glsl_name[8]; - - ptr = list_head( &This->glsl_shader_progs ); - while (ptr) { - /* At least one program exists - see if it matches our ps/vs combination */ - curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry ); - if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) { - /* Existing Program found, use it */ - TRACE_(d3d_shader)("Found existing program (%u) for this vertex/pixel shader combination\n", - curLink->programId); - This->stateBlock->glsl_program = curLink; - return; - } - /* This isn't the entry we need - try the next one */ - ptr = list_next( &This->glsl_shader_progs, ptr ); - } - - /* If we get to this point, then no matching program exists, so we create one */ - programId = GL_EXTCALL(glCreateProgramObjectARB()); - TRACE_(d3d_shader)("Created new GLSL shader program %u\n", programId); - - /* Allocate a new link for the list of programs */ - newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link)); - newLink->programId = programId; - This->stateBlock->glsl_program = newLink; - - /* Attach GLSL vshader */ - if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) { - int i; - int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */ - char tmp_name[10]; - - TRACE("Attaching vertex shader to GLSL program\n"); - attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader); - - /* Bind vertex attributes to a corresponding index number to match - * the same index numbers as ARB_vertex_programs (makes loading - * vertex attributes simpler). With this method, we can use the - * exact same code to load the attributes later for both ARB and - * GLSL shaders. - * - * We have to do this here because we need to know the Program ID - * in order to make the bindings work, and it has to be done prior - * to linking the GLSL program. */ - for (i = 0; i < max_attribs; ++i) { - snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i); - GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); - } - checkGLcall("glBindAttribLocationARB"); - newLink->vertexShader = vshader; - } - - /* Attach GLSL pshader */ - if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) { - TRACE("Attaching pixel shader to GLSL program\n"); - attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader); - newLink->pixelShader = pshader; - } - - /* Link the program */ - TRACE_(d3d_shader)("Linking GLSL shader program %u\n", programId); - GL_EXTCALL(glLinkProgramARB(programId)); - print_glsl_info_log(&GLINFO_LOCATION, programId); - list_add_head( &This->glsl_shader_progs, &newLink->entry); - - newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF)); - for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) { - snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i); - newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); - } - newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF)); - for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) { - snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i); - newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); - } - - return; -} - /** Detach the GLSL pixel or vertex shader object from the shader program */ static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) { diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 17b6a474c5e..7d95c51cd99 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -1879,6 +1879,123 @@ void vshader_glsl_output_unpack( } } +/** Attach a GLSL pixel or vertex shader object to the shader program */ +static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info; + GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId; + if (This->stateBlock->glsl_program && shaderObj != 0) { + TRACE("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId); + GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj)); + checkGLcall("glAttachObjectARB"); + } +} + +/** Sets the GLSL program ID for the given pixel and vertex shader combination. + * It sets the programId on the current StateBlock (because it should be called + * inside of the DrawPrimitive() part of the render loop). + * + * If a program for the given combination does not exist, create one, and store + * the program in the list. If it creates a program, it will link the given + * objects, too. + * + * We keep the shader programs around on a list because linking + * shader objects together is an expensive operation. It's much + * faster to loop through a list of pre-compiled & linked programs + * each time that the application sets a new pixel or vertex shader + * than it is to re-link them together at that time. + * + * The list will be deleted in IWineD3DDevice::Release(). + */ +static void set_glsl_shader_program(IWineD3DDevice *iface) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info; + IWineD3DPixelShader *pshader = This->stateBlock->pixelShader; + IWineD3DVertexShader *vshader = This->stateBlock->vertexShader; + struct glsl_shader_prog_link *curLink = NULL; + struct glsl_shader_prog_link *newLink = NULL; + struct list *ptr = NULL; + GLhandleARB programId = 0; + int i; + char glsl_name[8]; + + ptr = list_head( &This->glsl_shader_progs ); + while (ptr) { + /* At least one program exists - see if it matches our ps/vs combination */ + curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry ); + if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) { + /* Existing Program found, use it */ + TRACE("Found existing program (%u) for this vertex/pixel shader combination\n", + curLink->programId); + This->stateBlock->glsl_program = curLink; + return; + } + /* This isn't the entry we need - try the next one */ + ptr = list_next( &This->glsl_shader_progs, ptr ); + } + + /* If we get to this point, then no matching program exists, so we create one */ + programId = GL_EXTCALL(glCreateProgramObjectARB()); + TRACE("Created new GLSL shader program %u\n", programId); + + /* Allocate a new link for the list of programs */ + newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link)); + newLink->programId = programId; + This->stateBlock->glsl_program = newLink; + + /* Attach GLSL vshader */ + if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) { + int i; + int max_attribs = 16; /* TODO: Will this always be the case? It is at the moment... */ + char tmp_name[10]; + + TRACE("Attaching vertex shader to GLSL program\n"); + attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader); + + /* Bind vertex attributes to a corresponding index number to match + * the same index numbers as ARB_vertex_programs (makes loading + * vertex attributes simpler). With this method, we can use the + * exact same code to load the attributes later for both ARB and + * GLSL shaders. + * + * We have to do this here because we need to know the Program ID + * in order to make the bindings work, and it has to be done prior + * to linking the GLSL program. */ + for (i = 0; i < max_attribs; ++i) { + snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i); + GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name)); + } + checkGLcall("glBindAttribLocationARB"); + newLink->vertexShader = vshader; + } + + /* Attach GLSL pshader */ + if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) { + TRACE("Attaching pixel shader to GLSL program\n"); + attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader); + newLink->pixelShader = pshader; + } + + /* Link the program */ + TRACE("Linking GLSL shader program %u\n", programId); + GL_EXTCALL(glLinkProgramARB(programId)); + print_glsl_info_log(&GLINFO_LOCATION, programId); + list_add_head( &This->glsl_shader_progs, &newLink->entry); + + newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF)); + for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) { + snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i); + newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF)); + for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) { + snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i); + newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name)); + } + + return; +} + static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) { GLhandleARB program_id; GLhandleARB vshader_id, pshader_id; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index e3af89bd422..14d1b0e8a4b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1587,7 +1587,6 @@ extern void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg); extern void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg); /* GLSL helper functions */ -extern void set_glsl_shader_program(IWineD3DDevice *iface); extern void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG *arg); extern void shader_glsl_load_constants( IWineD3DDevice* device,