wined3d: Remove the forward declaration added in the last patch.
This commit is contained in:
parent
d0d681c81e
commit
732a9a15d5
|
@ -1926,232 +1926,6 @@ static GLuint create_arb_blt_fragment_program(const WineD3D_GL_Info *gl_info, en
|
|||
return program_id;
|
||||
}
|
||||
|
||||
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct ps_compile_args *args);
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
|
||||
{
|
||||
UINT i;
|
||||
DWORD new_size;
|
||||
struct ps_compiled_shader *new_array;
|
||||
SHADER_BUFFER buffer;
|
||||
|
||||
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
|
||||
* so a linear search is more performant than a hashmap or a binary search
|
||||
* (cache coherency etc)
|
||||
*/
|
||||
for(i = 0; i < shader->num_gl_shaders; i++) {
|
||||
if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
|
||||
return shader->gl_shaders[i].prgId;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("No matching GL shader found, compiling a new shader\n");
|
||||
if(shader->shader_array_size == shader->num_gl_shaders) {
|
||||
if (shader->num_gl_shaders)
|
||||
{
|
||||
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
|
||||
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
|
||||
new_size * sizeof(*shader->gl_shaders));
|
||||
} else {
|
||||
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
|
||||
new_size = 1;
|
||||
}
|
||||
|
||||
if(!new_array) {
|
||||
ERR("Out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
shader->gl_shaders = new_array;
|
||||
shader->shader_array_size = new_size;
|
||||
}
|
||||
|
||||
shader->gl_shaders[shader->num_gl_shaders].args = *args;
|
||||
|
||||
pixelshader_update_samplers(&shader->baseShader.reg_maps,
|
||||
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
|
||||
|
||||
shader_buffer_init(&buffer);
|
||||
shader->gl_shaders[shader->num_gl_shaders].prgId =
|
||||
shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args);
|
||||
shader_buffer_free(&buffer);
|
||||
|
||||
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (useVS) {
|
||||
struct vs_compile_args compile_args;
|
||||
|
||||
TRACE("Using vertex shader\n");
|
||||
find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
|
||||
priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
|
||||
|
||||
/* Bind the vertex program */
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
|
||||
|
||||
/* Enable OpenGL vertex programs */
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
|
||||
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
|
||||
} else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
|
||||
priv->current_vprogram_id = 0;
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
|
||||
}
|
||||
|
||||
if (usePS) {
|
||||
struct ps_compile_args compile_args;
|
||||
TRACE("Using pixel shader\n");
|
||||
find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args);
|
||||
priv->current_fprogram_id = find_arb_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader,
|
||||
&compile_args);
|
||||
|
||||
/* Bind the fragment program */
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
|
||||
|
||||
if(!priv->use_arbfp_fixed_func) {
|
||||
/* Enable OpenGL fragment programs */
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
|
||||
}
|
||||
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
|
||||
|
||||
shader_arb_ps_local_constants(This);
|
||||
} else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) {
|
||||
/* Disable only if we're not using arbfp fixed function fragment processing. If this is used,
|
||||
* keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function
|
||||
* replacement shader
|
||||
*/
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
|
||||
priv->current_fprogram_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type];
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
|
||||
if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type);
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (priv->current_vprogram_id) {
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
|
||||
|
||||
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
|
||||
} else {
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
|
||||
}
|
||||
|
||||
if (priv->current_fprogram_id) {
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
|
||||
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
|
||||
|
||||
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
|
||||
} else {
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
|
||||
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
|
||||
|
||||
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
|
||||
{
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
|
||||
UINT i;
|
||||
|
||||
ENTER_GL();
|
||||
for(i = 0; i < This->num_gl_shaders; i++) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
|
||||
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
|
||||
}
|
||||
LEAVE_GL();
|
||||
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
|
||||
This->gl_shaders = NULL;
|
||||
This->num_gl_shaders = 0;
|
||||
This->shader_array_size = 0;
|
||||
} else {
|
||||
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
|
||||
UINT i;
|
||||
|
||||
ENTER_GL();
|
||||
for(i = 0; i < This->num_gl_shaders; i++) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
|
||||
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
|
||||
}
|
||||
LEAVE_GL();
|
||||
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
|
||||
This->gl_shaders = NULL;
|
||||
This->num_gl_shaders = 0;
|
||||
This->shader_array_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv));
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
static void shader_arb_free(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
int i;
|
||||
|
||||
ENTER_GL();
|
||||
if(priv->depth_blt_vprogram_id) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
|
||||
}
|
||||
for (i = 0; i < tex_type_count; ++i) {
|
||||
if (priv->depth_blt_fprogram_id[i]) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i]));
|
||||
}
|
||||
}
|
||||
LEAVE_GL();
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
||||
}
|
||||
|
||||
static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1,
|
||||
const char *tmp2, const char *tmp3) {
|
||||
/* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
|
||||
|
@ -2169,7 +1943,6 @@ static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcol
|
|||
shader_addline(buffer, "CMP result.color.xyz, %s, %s, %s;\n", tmp3, tmp2, tmp1);
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
|
||||
{
|
||||
|
@ -2427,6 +2200,229 @@ static GLuint shader_arb_generate_vshader(IWineD3DVertexShader *iface,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
|
||||
{
|
||||
UINT i;
|
||||
DWORD new_size;
|
||||
struct ps_compiled_shader *new_array;
|
||||
SHADER_BUFFER buffer;
|
||||
|
||||
/* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
|
||||
* so a linear search is more performant than a hashmap or a binary search
|
||||
* (cache coherency etc)
|
||||
*/
|
||||
for(i = 0; i < shader->num_gl_shaders; i++) {
|
||||
if(memcmp(&shader->gl_shaders[i].args, args, sizeof(*args)) == 0) {
|
||||
return shader->gl_shaders[i].prgId;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("No matching GL shader found, compiling a new shader\n");
|
||||
if(shader->shader_array_size == shader->num_gl_shaders) {
|
||||
if (shader->num_gl_shaders)
|
||||
{
|
||||
new_size = shader->shader_array_size + max(1, shader->shader_array_size / 2);
|
||||
new_array = HeapReAlloc(GetProcessHeap(), 0, shader->gl_shaders,
|
||||
new_size * sizeof(*shader->gl_shaders));
|
||||
} else {
|
||||
new_array = HeapAlloc(GetProcessHeap(), 0, sizeof(*shader->gl_shaders));
|
||||
new_size = 1;
|
||||
}
|
||||
|
||||
if(!new_array) {
|
||||
ERR("Out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
shader->gl_shaders = new_array;
|
||||
shader->shader_array_size = new_size;
|
||||
}
|
||||
|
||||
shader->gl_shaders[shader->num_gl_shaders].args = *args;
|
||||
|
||||
pixelshader_update_samplers(&shader->baseShader.reg_maps,
|
||||
((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
|
||||
|
||||
shader_buffer_init(&buffer);
|
||||
shader->gl_shaders[shader->num_gl_shaders].prgId =
|
||||
shader_arb_generate_pshader((IWineD3DPixelShader *)shader, &buffer, args);
|
||||
shader_buffer_free(&buffer);
|
||||
|
||||
return shader->gl_shaders[shader->num_gl_shaders++].prgId;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (useVS) {
|
||||
struct vs_compile_args compile_args;
|
||||
|
||||
TRACE("Using vertex shader\n");
|
||||
find_vs_compile_args((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, This->stateBlock, &compile_args);
|
||||
priv->current_vprogram_id = find_gl_vshader((IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader, &compile_args);
|
||||
|
||||
/* Bind the vertex program */
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
|
||||
|
||||
/* Enable OpenGL vertex programs */
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
|
||||
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
|
||||
} else if(GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
|
||||
priv->current_vprogram_id = 0;
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
|
||||
}
|
||||
|
||||
if (usePS) {
|
||||
struct ps_compile_args compile_args;
|
||||
TRACE("Using pixel shader\n");
|
||||
find_ps_compile_args((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader, This->stateBlock, &compile_args);
|
||||
priv->current_fprogram_id = find_arb_pshader((IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader,
|
||||
&compile_args);
|
||||
|
||||
/* Bind the fragment program */
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
|
||||
|
||||
if(!priv->use_arbfp_fixed_func) {
|
||||
/* Enable OpenGL fragment programs */
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
|
||||
}
|
||||
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
|
||||
|
||||
shader_arb_ps_local_constants(This);
|
||||
} else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && !priv->use_arbfp_fixed_func) {
|
||||
/* Disable only if we're not using arbfp fixed function fragment processing. If this is used,
|
||||
* keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function
|
||||
* replacement shader
|
||||
*/
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
|
||||
priv->current_fprogram_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
GLuint *blt_fprogram = &priv->depth_blt_fprogram_id[tex_type];
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
|
||||
if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type);
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
|
||||
if (priv->current_vprogram_id) {
|
||||
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
|
||||
|
||||
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
|
||||
|
||||
TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
|
||||
} else {
|
||||
glDisable(GL_VERTEX_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
|
||||
}
|
||||
|
||||
if (priv->current_fprogram_id) {
|
||||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
|
||||
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
|
||||
|
||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
|
||||
|
||||
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
|
||||
} else {
|
||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
|
||||
}
|
||||
}
|
||||
|
||||
static void shader_arb_destroy(IWineD3DBaseShader *iface) {
|
||||
IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)baseShader->baseShader.device)->adapter->gl_info;
|
||||
|
||||
if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
|
||||
{
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *) iface;
|
||||
UINT i;
|
||||
|
||||
ENTER_GL();
|
||||
for(i = 0; i < This->num_gl_shaders; i++) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
|
||||
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
|
||||
}
|
||||
LEAVE_GL();
|
||||
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
|
||||
This->gl_shaders = NULL;
|
||||
This->num_gl_shaders = 0;
|
||||
This->shader_array_size = 0;
|
||||
} else {
|
||||
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *) iface;
|
||||
UINT i;
|
||||
|
||||
ENTER_GL();
|
||||
for(i = 0; i < This->num_gl_shaders; i++) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId));
|
||||
checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &This->gl_shaders[i].prgId))");
|
||||
}
|
||||
LEAVE_GL();
|
||||
HeapFree(GetProcessHeap(), 0, This->gl_shaders);
|
||||
This->gl_shaders = NULL;
|
||||
This->num_gl_shaders = 0;
|
||||
This->shader_array_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
This->shader_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv));
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
static void shader_arb_free(IWineD3DDevice *iface) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
|
||||
struct shader_arb_priv *priv = This->shader_priv;
|
||||
int i;
|
||||
|
||||
ENTER_GL();
|
||||
if(priv->depth_blt_vprogram_id) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
|
||||
}
|
||||
for (i = 0; i < tex_type_count; ++i) {
|
||||
if (priv->depth_blt_fprogram_id[i]) {
|
||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id[i]));
|
||||
}
|
||||
}
|
||||
LEAVE_GL();
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, This->shader_priv);
|
||||
}
|
||||
|
||||
static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void shader_arb_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
|
||||
{
|
||||
/* We don't have an ARB fixed function pipeline yet, so let the none backend set its caps,
|
||||
|
|
|
@ -3608,8 +3608,185 @@ static void hardcode_local_constants(IWineD3DBaseShaderImpl *shader, const WineD
|
|||
checkGLcall("Hardcoding local constants\n");
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct ps_compile_args *args);
|
||||
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
|
||||
{
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
||||
CONST DWORD *function = This->baseShader.function;
|
||||
const char *fragcolor;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
|
||||
struct shader_glsl_ctx_priv priv_ctx;
|
||||
|
||||
/* Create the hw GLSL shader object and assign it as the shader->prgId */
|
||||
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
|
||||
|
||||
memset(&priv_ctx, 0, sizeof(priv_ctx));
|
||||
priv_ctx.cur_ps_args = args;
|
||||
|
||||
shader_addline(buffer, "#version 120\n");
|
||||
|
||||
if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
||||
shader_addline(buffer, "#extension GL_ARB_draw_buffers : enable\n");
|
||||
}
|
||||
if(GL_SUPPORT(ARB_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) {
|
||||
shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
|
||||
}
|
||||
if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
|
||||
/* The spec says that it doesn't have to be explicitly enabled, but the nvidia
|
||||
* drivers write a warning if we don't do so
|
||||
*/
|
||||
shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
|
||||
}
|
||||
|
||||
/* Base Declarations */
|
||||
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, args);
|
||||
|
||||
/* Pack 3.0 inputs */
|
||||
if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
|
||||
{
|
||||
pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode);
|
||||
}
|
||||
|
||||
/* Base Shader Body */
|
||||
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
|
||||
|
||||
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
|
||||
if (reg_maps->shader_version.major < 2)
|
||||
{
|
||||
/* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */
|
||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS))
|
||||
shader_addline(buffer, "gl_FragData[0] = R0;\n");
|
||||
else
|
||||
shader_addline(buffer, "gl_FragColor = R0;\n");
|
||||
}
|
||||
|
||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
||||
fragcolor = "gl_FragData[0]";
|
||||
} else {
|
||||
fragcolor = "gl_FragColor";
|
||||
}
|
||||
if(args->srgb_correction) {
|
||||
shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
|
||||
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
|
||||
srgb_sub_high, srgb_sub_high, srgb_sub_high);
|
||||
shader_addline(buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor);
|
||||
shader_addline(buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
|
||||
}
|
||||
/* Pixel shader < 3.0 do not replace the fog stage.
|
||||
* This implements linear fog computation and blending.
|
||||
* TODO: non linear fog
|
||||
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
|
||||
* -1/(e-s) and e/(e-s) respectively.
|
||||
*/
|
||||
if (reg_maps->shader_version.major < 3)
|
||||
{
|
||||
switch(args->fog) {
|
||||
case FOG_OFF: break;
|
||||
case FOG_LINEAR:
|
||||
shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n");
|
||||
shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n");
|
||||
shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
case FOG_EXP:
|
||||
/* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */
|
||||
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
|
||||
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
case FOG_EXP2:
|
||||
/* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */
|
||||
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
|
||||
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shader_addline(buffer, "}\n");
|
||||
|
||||
TRACE("Compiling shader object %u\n", shader_obj);
|
||||
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
|
||||
GL_EXTCALL(glCompileShaderARB(shader_obj));
|
||||
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
|
||||
|
||||
/* Store the shader object */
|
||||
return shader_obj;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct vs_compile_args *args)
|
||||
{
|
||||
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
|
||||
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
||||
CONST DWORD *function = This->baseShader.function;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
|
||||
struct shader_glsl_ctx_priv priv_ctx;
|
||||
|
||||
/* Create the hw GLSL shader program and assign it as the shader->prgId */
|
||||
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
|
||||
|
||||
shader_addline(buffer, "#version 120\n");
|
||||
|
||||
memset(&priv_ctx, 0, sizeof(priv_ctx));
|
||||
priv_ctx.cur_vs_args = args;
|
||||
|
||||
/* Base Declarations */
|
||||
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
|
||||
|
||||
/* Base Shader Body */
|
||||
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx);
|
||||
|
||||
/* Unpack 3.0 outputs */
|
||||
if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");
|
||||
else shader_addline(buffer, "order_ps_input();\n");
|
||||
|
||||
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
|
||||
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
|
||||
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
|
||||
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
|
||||
*/
|
||||
if(args->fog_src == VS_FOG_Z) {
|
||||
shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
|
||||
} else if (!reg_maps->fog) {
|
||||
shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
|
||||
}
|
||||
|
||||
/* Write the final position.
|
||||
*
|
||||
* OpenGL coordinates specify the center of the pixel while d3d coords specify
|
||||
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
|
||||
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
|
||||
* contains 1.0 to allow a mad.
|
||||
*/
|
||||
shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n");
|
||||
shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n");
|
||||
shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
|
||||
|
||||
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
|
||||
*
|
||||
* Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run
|
||||
* before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w,
|
||||
* which is the same as z = z * 2 - w.
|
||||
*/
|
||||
shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
|
||||
|
||||
shader_addline(buffer, "}\n");
|
||||
|
||||
TRACE("Compiling shader object %u\n", shader_obj);
|
||||
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
|
||||
GL_EXTCALL(glCompileShaderARB(shader_obj));
|
||||
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
|
||||
|
||||
return shader_obj;
|
||||
}
|
||||
|
||||
static GLhandleARB find_glsl_pshader(IWineD3DPixelShaderImpl *shader, const struct ps_compile_args *args)
|
||||
{
|
||||
|
@ -4213,185 +4390,6 @@ static BOOL shader_glsl_dirty_const(IWineD3DDevice *iface) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct ps_compile_args *args)
|
||||
{
|
||||
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
|
||||
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
||||
CONST DWORD *function = This->baseShader.function;
|
||||
const char *fragcolor;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
|
||||
struct shader_glsl_ctx_priv priv_ctx;
|
||||
|
||||
/* Create the hw GLSL shader object and assign it as the shader->prgId */
|
||||
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
|
||||
|
||||
memset(&priv_ctx, 0, sizeof(priv_ctx));
|
||||
priv_ctx.cur_ps_args = args;
|
||||
|
||||
shader_addline(buffer, "#version 120\n");
|
||||
|
||||
if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
||||
shader_addline(buffer, "#extension GL_ARB_draw_buffers : enable\n");
|
||||
}
|
||||
if(GL_SUPPORT(ARB_SHADER_TEXTURE_LOD) && reg_maps->usestexldd) {
|
||||
shader_addline(buffer, "#extension GL_ARB_shader_texture_lod : enable\n");
|
||||
}
|
||||
if (GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
|
||||
/* The spec says that it doesn't have to be explicitly enabled, but the nvidia
|
||||
* drivers write a warning if we don't do so
|
||||
*/
|
||||
shader_addline(buffer, "#extension GL_ARB_texture_rectangle : enable\n");
|
||||
}
|
||||
|
||||
/* Base Declarations */
|
||||
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, args);
|
||||
|
||||
/* Pack 3.0 inputs */
|
||||
if (reg_maps->shader_version.major >= 3 && args->vp_mode != vertexshader)
|
||||
{
|
||||
pshader_glsl_input_pack(iface, buffer, This->input_signature, reg_maps, args->vp_mode);
|
||||
}
|
||||
|
||||
/* Base Shader Body */
|
||||
shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
|
||||
|
||||
/* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
|
||||
if (reg_maps->shader_version.major < 2)
|
||||
{
|
||||
/* Some older cards like GeforceFX ones don't support multiple buffers, so also not gl_FragData */
|
||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS))
|
||||
shader_addline(buffer, "gl_FragData[0] = R0;\n");
|
||||
else
|
||||
shader_addline(buffer, "gl_FragColor = R0;\n");
|
||||
}
|
||||
|
||||
if(GL_SUPPORT(ARB_DRAW_BUFFERS)) {
|
||||
fragcolor = "gl_FragData[0]";
|
||||
} else {
|
||||
fragcolor = "gl_FragColor";
|
||||
}
|
||||
if(args->srgb_correction) {
|
||||
shader_addline(buffer, "tmp0.xyz = pow(%s.xyz, vec3(%f, %f, %f)) * vec3(%f, %f, %f) - vec3(%f, %f, %f);\n",
|
||||
fragcolor, srgb_pow, srgb_pow, srgb_pow, srgb_mul_high, srgb_mul_high, srgb_mul_high,
|
||||
srgb_sub_high, srgb_sub_high, srgb_sub_high);
|
||||
shader_addline(buffer, "tmp1.xyz = %s.xyz * srgb_mul_low.xyz;\n", fragcolor);
|
||||
shader_addline(buffer, "%s.x = %s.x < srgb_comparison.x ? tmp1.x : tmp0.x;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s.y = %s.y < srgb_comparison.y ? tmp1.y : tmp0.y;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s.z = %s.z < srgb_comparison.z ? tmp1.z : tmp0.z;\n", fragcolor, fragcolor);
|
||||
shader_addline(buffer, "%s = clamp(%s, 0.0, 1.0);\n", fragcolor, fragcolor);
|
||||
}
|
||||
/* Pixel shader < 3.0 do not replace the fog stage.
|
||||
* This implements linear fog computation and blending.
|
||||
* TODO: non linear fog
|
||||
* NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
|
||||
* -1/(e-s) and e/(e-s) respectively.
|
||||
*/
|
||||
if (reg_maps->shader_version.major < 3)
|
||||
{
|
||||
switch(args->fog) {
|
||||
case FOG_OFF: break;
|
||||
case FOG_LINEAR:
|
||||
shader_addline(buffer, "float fogstart = -1.0 / (gl_Fog.end - gl_Fog.start);\n");
|
||||
shader_addline(buffer, "float fogend = gl_Fog.end * -fogstart;\n");
|
||||
shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * fogstart + fogend, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
case FOG_EXP:
|
||||
/* Fog = e^(-gl_Fog.density * gl_FogFragCoord) */
|
||||
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_FogFragCoord);\n");
|
||||
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
case FOG_EXP2:
|
||||
/* Fog = e^(-(gl_Fog.density * gl_FogFragCoord)^2) */
|
||||
shader_addline(buffer, "float Fog = exp(-gl_Fog.density * gl_Fog.density * gl_FogFragCoord * gl_FogFragCoord);\n");
|
||||
shader_addline(buffer, "Fog = clamp(Fog, 0.0, 1.0);\n");
|
||||
shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shader_addline(buffer, "}\n");
|
||||
|
||||
TRACE("Compiling shader object %u\n", shader_obj);
|
||||
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
|
||||
GL_EXTCALL(glCompileShaderARB(shader_obj));
|
||||
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
|
||||
|
||||
/* Store the shader object */
|
||||
return shader_obj;
|
||||
}
|
||||
|
||||
/* GL locking is done by the caller */
|
||||
static GLuint shader_glsl_generate_vshader(IWineD3DVertexShader *iface,
|
||||
SHADER_BUFFER *buffer, const struct vs_compile_args *args)
|
||||
{
|
||||
IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
|
||||
const struct shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
|
||||
CONST DWORD *function = This->baseShader.function;
|
||||
const WineD3D_GL_Info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
|
||||
struct shader_glsl_ctx_priv priv_ctx;
|
||||
|
||||
/* Create the hw GLSL shader program and assign it as the shader->prgId */
|
||||
GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
|
||||
|
||||
shader_addline(buffer, "#version 120\n");
|
||||
|
||||
memset(&priv_ctx, 0, sizeof(priv_ctx));
|
||||
priv_ctx.cur_vs_args = args;
|
||||
|
||||
/* Base Declarations */
|
||||
shader_generate_glsl_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION, NULL);
|
||||
|
||||
/* Base Shader Body */
|
||||
shader_generate_main((IWineD3DBaseShader*)This, buffer, reg_maps, function, &priv_ctx);
|
||||
|
||||
/* Unpack 3.0 outputs */
|
||||
if (reg_maps->shader_version.major >= 3) shader_addline(buffer, "order_ps_input(OUT);\n");
|
||||
else shader_addline(buffer, "order_ps_input();\n");
|
||||
|
||||
/* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
|
||||
* or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
|
||||
* the fog frag coord is thrown away. If the fog frag coord is used, but not written by
|
||||
* the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
|
||||
*/
|
||||
if(args->fog_src == VS_FOG_Z) {
|
||||
shader_addline(buffer, "gl_FogFragCoord = gl_Position.z;\n");
|
||||
} else if (!reg_maps->fog) {
|
||||
shader_addline(buffer, "gl_FogFragCoord = 0.0;\n");
|
||||
}
|
||||
|
||||
/* Write the final position.
|
||||
*
|
||||
* OpenGL coordinates specify the center of the pixel while d3d coords specify
|
||||
* the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
|
||||
* 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
|
||||
* contains 1.0 to allow a mad.
|
||||
*/
|
||||
shader_addline(buffer, "gl_Position.y = gl_Position.y * posFixup.y;\n");
|
||||
shader_addline(buffer, "gl_Position.xy += posFixup.zw * gl_Position.ww;\n");
|
||||
shader_addline(buffer, "gl_ClipVertex = gl_Position;\n");
|
||||
|
||||
/* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
|
||||
*
|
||||
* Basically we want (in homogeneous coordinates) z = z * 2 - 1. However, shaders are run
|
||||
* before the homogeneous divide, so we have to take the w into account: z = ((z / w) * 2 - 1) * w,
|
||||
* which is the same as z = z * 2 - w.
|
||||
*/
|
||||
shader_addline(buffer, "gl_Position.z = gl_Position.z * 2.0 - gl_Position.w;\n");
|
||||
|
||||
shader_addline(buffer, "}\n");
|
||||
|
||||
TRACE("Compiling shader object %u\n", shader_obj);
|
||||
GL_EXTCALL(glShaderSourceARB(shader_obj, 1, (const char**)&buffer->buffer, NULL));
|
||||
GL_EXTCALL(glCompileShaderARB(shader_obj));
|
||||
print_glsl_info_log(&GLINFO_LOCATION, shader_obj);
|
||||
|
||||
return shader_obj;
|
||||
}
|
||||
|
||||
static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct shader_caps *pCaps)
|
||||
{
|
||||
/* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
|
||||
|
|
Loading…
Reference in New Issue