Module: wine Branch: master Commit: 14eedc5be7f27e55f50bd4a3c01d355b4a986542 URL: http://source.winehq.org/git/wine.git/?a=commit;h=14eedc5be7f27e55f50bd4a3c0...
Author: Stefan Dösinger stefan@codeweavers.com Date: Thu Aug 6 20:30:20 2009 +0200
wined3d: Watch out about higher constants when clamping ps 1.x consts.
ps 1.x supports only 8 constants, so the shader load code dirtifies the first 8 on a shader switch. However, the constant load code reloaded all dirty consts with clamping. That potentially left constants > 8 clamped.
---
dlls/wined3d/arb_program_shader.c | 61 ++++++++++++++++++++++--------------- 1 files changed, 36 insertions(+), 25 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 6300abb..4ed57a0 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -284,7 +284,7 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts) { local_constant* lconst; - DWORD i, j; + DWORD i = 0, j; unsigned int ret;
if (TRACE_ON(d3d_shader)) { @@ -299,7 +299,10 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1) { float lcl_const[4]; - for(i = 0; i < max_constants; i++) { + /* ps 1.x supports only 8 constants, clamp only those. When switching between 1.x and higher + * shaders, the first 8 constants are marked dirty for reload + */ + for(; i < min(8, max_constants); i++) { if(!dirty_consts[i]) continue; dirty_consts[i] = 0;
@@ -322,31 +325,39 @@ static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, con
GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const)); } - } else { - if(GL_SUPPORT(EXT_GPU_PROGRAM_PARAMETERS)) { - /* TODO: Benchmark if we're better of with finding the dirty constants ourselves, - * or just reloading *all* constants at once - * - GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, 0, max_constants, constants)); - */ - for(i = 0; i < max_constants; i++) { - if(!dirty_consts[i]) continue;
- /* Find the next block of dirty constants */ - dirty_consts[i] = 0; - j = i; - for(i++; (i < max_constants) && dirty_consts[i]; i++) { - dirty_consts[i] = 0; - } + /* If further constants are dirty, reload them without clamping. + * + * The alternative is not to touch them, but then we cannot reset the dirty constant count + * to zero. That's bad for apps that only use PS 1.x shaders, because in that case the code + * above would always re-check the first 8 constants since max_constant remains at the init + * value + */ + } + + if(GL_SUPPORT(EXT_GPU_PROGRAM_PARAMETERS)) { + /* TODO: Benchmark if we're better of with finding the dirty constants ourselves, + * or just reloading *all* constants at once + * + GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, i, max_constants, constants + (i * 4))); + */ + for(; i < max_constants; i++) { + if(!dirty_consts[i]) continue;
- GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4))); + /* Find the next block of dirty constants */ + dirty_consts[i] = 0; + j = i; + for(i++; (i < max_constants) && dirty_consts[i]; i++) { + dirty_consts[i] = 0; } - } else { - for(i = 0; i < max_constants; i++) { - if(dirty_consts[i]) { - dirty_consts[i] = 0; - GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); - } + + GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4))); + } + } else { + for(; i < max_constants; i++) { + if(dirty_consts[i]) { + dirty_consts[i] = 0; + GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4))); } } }