wined3d: Move set_glsl_shader_program() to glsl_shader.c.
This commit is contained in:
parent
045975b1f4
commit
c972351051
|
@ -251,123 +251,6 @@ static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightIn
|
||||||
* GLSL helper functions follow
|
* 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 */
|
/** Detach the GLSL pixel or vertex shader object from the shader program */
|
||||||
static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
|
static void detach_glsl_shader(IWineD3DDevice *iface, GLhandleARB shaderObj, GLhandleARB programId) {
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) {
|
||||||
GLhandleARB program_id;
|
GLhandleARB program_id;
|
||||||
GLhandleARB vshader_id, pshader_id;
|
GLhandleARB vshader_id, pshader_id;
|
||||||
|
|
|
@ -1587,7 +1587,6 @@ extern void vshader_hw_map2gl(SHADER_OPCODE_ARG* arg);
|
||||||
extern void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
|
extern void vshader_hw_mnxn(SHADER_OPCODE_ARG* arg);
|
||||||
|
|
||||||
/* GLSL helper functions */
|
/* 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_add_instruction_modifiers(SHADER_OPCODE_ARG *arg);
|
||||||
extern void shader_glsl_load_constants(
|
extern void shader_glsl_load_constants(
|
||||||
IWineD3DDevice* device,
|
IWineD3DDevice* device,
|
||||||
|
|
Loading…
Reference in New Issue