wined3d: Don't call shader_select() in depth_blt().

Calling shader_select() from inside depth_blt() isn't necessarily
safe. shader_select() assumes CompileShader() has been called for the
current shaders, but that depends on STATE_VSHADER / STATE_PIXELSHADER
being applied. That isn't always true when depth_blt() gets called,
with the result that sometimes GLSL programs could be created with no
shader objects attached.
oldstable
H. Verbeet 2008-07-10 17:57:35 +02:00 committed by Alexandre Julliard
parent d2cce3284a
commit b37cc08721
6 changed files with 69 additions and 13 deletions

View File

@ -1766,22 +1766,24 @@ static GLuint create_arb_blt_fragment_program(WineD3D_GL_Info *gl_info) {
static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv;
WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
if (useVS) {
TRACE("Using vertex shader\n");
priv->current_vprogram_id = ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId;
/* Bind the vertex program */
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB,
((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId));
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
/* 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, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId);
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)");
}
@ -1789,17 +1791,18 @@ static void shader_arb_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
if (usePS) {
TRACE("Using pixel shader\n");
priv->current_fprogram_id = ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId;
/* Bind the fragment program */
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB,
((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId));
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
/* 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, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.prgId);
TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
} else if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
priv->current_fprogram_id = 0;
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
}
@ -1819,6 +1822,38 @@ static void shader_arb_select_depth_blt(IWineD3DDevice *iface) {
glEnable(GL_FRAGMENT_PROGRAM_ARB);
}
static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
struct shader_arb_priv *priv = (struct shader_arb_priv *) This->shader_priv;
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 if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
glDisable(GL_FRAGMENT_PROGRAM_ARB);
checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
}
}
static void shader_arb_cleanup(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
@ -2092,6 +2127,7 @@ static void shader_arb_fragment_enable(IWineD3DDevice *iface, BOOL enable) {
const shader_backend_t arb_program_shader_backend = {
shader_arb_select,
shader_arb_select_depth_blt,
shader_arb_deselect_depth_blt,
shader_arb_load_constants,
shader_arb_cleanup,
shader_arb_color_correction,

View File

@ -976,6 +976,10 @@ static void shader_atifs_select_depth_blt(IWineD3DDevice *iface) {
arb_program_shader_backend.shader_select_depth_blt(iface);
}
static void shader_atifs_deselect_depth_blt(IWineD3DDevice *iface) {
arb_program_shader_backend.shader_deselect_depth_blt(iface);
}
static void shader_atifs_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {
arb_program_shader_backend.shader_load_constants(iface, usePS, useVS);
}
@ -1107,6 +1111,7 @@ static void shader_atifs_fragment_enable(IWineD3DDevice *iface, BOOL enable) {
const shader_backend_t atifs_shader_backend = {
shader_atifs_select,
shader_atifs_select_depth_blt,
shader_atifs_deselect_depth_blt,
shader_atifs_load_constants,
shader_atifs_cleanup,
shader_atifs_color_correction,

View File

@ -1091,6 +1091,7 @@ void shader_trace_init(
static void shader_none_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {}
static void shader_none_select_depth_blt(IWineD3DDevice *iface) {}
static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
static void shader_none_cleanup(IWineD3DDevice *iface) {}
static void shader_none_color_correction(SHADER_OPCODE_ARG* arg) {}
@ -1201,6 +1202,7 @@ static void shader_none_fragment_enable(IWineD3DDevice *iface, BOOL enable) {
const shader_backend_t none_shader_backend = {
shader_none_select,
shader_none_select_depth_blt,
shader_none_deselect_depth_blt,
shader_none_load_constants,
shader_none_cleanup,
shader_none_color_correction,

View File

@ -753,11 +753,7 @@ void depth_blt(IWineD3DDevice *iface, GLuint texture) {
glPopAttrib();
/* Reselect the old shaders. There doesn't seem to be any glPushAttrib bit for arb shaders,
* and this seems easier and more efficient than providing the shader backend with a private
* storage to read and restore the old shader settings
*/
This->shader_backend->shader_select(iface, use_ps(This), use_vs(This));
This->shader_backend->shader_deselect_depth_blt(iface);
}
static inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, UINT numberOfVertices,

View File

@ -3398,6 +3398,19 @@ static void shader_glsl_select_depth_blt(IWineD3DDevice *iface) {
GL_EXTCALL(glUniform1iARB(loc, 0));
}
static void shader_glsl_deselect_depth_blt(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
struct shader_glsl_priv *priv = (struct shader_glsl_priv *) This->shader_priv;
GLhandleARB program_id;
program_id = priv->glsl_program ? priv->glsl_program->programId : 0;
if (program_id) TRACE("Using GLSL program %u\n", program_id);
GL_EXTCALL(glUseProgramObjectARB(program_id));
checkGLcall("glUseProgramObjectARB");
}
static void shader_glsl_cleanup(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
@ -3695,6 +3708,7 @@ static void shader_glsl_fragment_enable(IWineD3DDevice *iface, BOOL enable) {
const shader_backend_t glsl_shader_backend = {
shader_glsl_select,
shader_glsl_select_depth_blt,
shader_glsl_deselect_depth_blt,
shader_glsl_load_constants,
shader_glsl_cleanup,
shader_glsl_color_correction,

View File

@ -242,6 +242,7 @@ struct shader_caps {
typedef struct {
void (*shader_select)(IWineD3DDevice *iface, BOOL usePS, BOOL useVS);
void (*shader_select_depth_blt)(IWineD3DDevice *iface);
void (*shader_deselect_depth_blt)(IWineD3DDevice *iface);
void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS);
void (*shader_cleanup)(IWineD3DDevice *iface);
void (*shader_color_correction)(struct SHADER_OPCODE_ARG *arg);
@ -269,6 +270,8 @@ struct shader_glsl_priv {
/* ARB_program_shader private data */
struct shader_arb_priv {
GLuint current_vprogram_id;
GLuint current_fprogram_id;
GLuint depth_blt_vprogram_id;
GLuint depth_blt_fprogram_id;
};