Module: wine Branch: master Commit: 49a49fcfec199ce6e972ee339fa28fbbe4643435 URL: http://source.winehq.org/git/wine.git/?a=commit;h=49a49fcfec199ce6e972ee339f...
Author: Stefan Dösinger stefan@codeweavers.com Date: Thu Feb 15 03:05:17 2007 +0100
wined3d: Load one bump mapping environment matrix into pixel shaders if needed.
---
dlls/wined3d/baseshader.c | 9 +++++++++ dlls/wined3d/directx.c | 9 ++++++++- dlls/wined3d/glsl_shader.c | 18 ++++++++++++++++-- dlls/wined3d/pixelshader.c | 2 ++ dlls/wined3d/state.c | 12 ++++++++++++ dlls/wined3d/wined3d_private.h | 5 +++++ 6 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index f13d448..3bbdb45 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -344,6 +344,15 @@ HRESULT shader_get_registers_used( reg_maps->samplers[sampler_code] = (0x1 << 31) | WINED3DSTT_2D; } } + + /* texbem is only valid with < 1.4 pixel shaders */ + if(WINED3DSIO_TEXBEM == curOpcode->opcode) { + if(reg_maps->bumpmat != 0 && reg_maps->bumpmat != sampler_code) { + FIXME("Pixel shader uses texbem instruction on more than 1 sampler\n"); + } else { + reg_maps->bumpmat = sampler_code; + } + } }
/* This will loop over all the registers and try to diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 7e2fc05..398aca0 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -284,10 +284,17 @@ void select_shader_max_constants(
switch (ps_selected_mode) { case SHADER_GLSL: - /* Subtract the other potential uniforms from the max available (bools & ints) */ + /* Subtract the other potential uniforms from the max available (bools & ints). + * In theory the texbem instruction may need one more shader constant too. But lets assume + * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card, + * and lets not take away a uniform needlessly from all other shaders. + */ gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; break; case SHADER_ARB: + /* The arb shader only loads the bump mapping environment matrix into the shader if it finds + * a free constant to do that, so no need to reduce the number of available constants. + */ gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF; break; case SHADER_SW: diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 9722312..566442b 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -283,7 +283,8 @@ void shader_glsl_load_constants( GLhandleARB *constant_locations; struct list *constant_list; GLhandleARB programId; - + GLint pos; + if (!stateBlock->glsl_program) { /* No GLSL program set - nothing to do. */ return; @@ -336,11 +337,22 @@ void shader_glsl_load_constants( shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I, stateBlock->pixelShaderConstantI, stateBlock->set.pixelShaderConstantsI); - + /* Load DirectX 9 boolean constants/uniforms for pixel shader */ shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B, stateBlock->pixelShaderConstantB, stateBlock->set.pixelShaderConstantsB); + + /* Upload the environment bump map matrix if needed. The needsbumpmat member specifies the texture stage to load the matrix from. + * It can't be 0 for a valid texbem instruction. + */ + if(((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat != 0) { + float *data = (float *) &stateBlock->textureState[(int) ((IWineD3DPixelShaderImpl *) pshader)->needsbumpmat][WINED3DTSS_BUMPENVMAT00]; + pos = GL_EXTCALL(glGetUniformLocationARB(programId, "bumpenvmat")); + checkGLcall("glGetUniformLocationARB"); + GL_EXTCALL(glUniform4fvARB(pos, 1, data)); + checkGLcall("glUniform4fvARB"); + } } }
@@ -379,6 +391,8 @@ void shader_generate_glsl_declarations(
if(!pshader) shader_addline(buffer, "uniform vec4 posFixup;\n"); + else if(reg_maps->bumpmat) + shader_addline(buffer, "uniform vec4 bumpenvmat;\n");
/* Declare texture samplers */ for (i = 0; i < This->baseShader.limits.sampler; i++) { diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index 8958ee0..e83cab1 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -914,6 +914,8 @@ inline static VOID IWineD3DPixelShaderImpl_GenerateShader( } }
+ This->needsbumpmat = reg_maps->bumpmat; + #if 1 /* if were using the data buffer of device then we don't need to free it */ HeapFree(GetProcessHeap(), 0, buffer.buffer); #endif diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 769f0d1..438f6f0 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -1951,6 +1951,18 @@ static void pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D }
static void tex_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { + DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / WINED3D_HIGHEST_TEXTURE_STATE; + + if(stateblock->pixelShader && stage != 0 && + ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->needsbumpmat == stage) { + /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled + * anyway + */ + if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) && + !isStateDirty(context, STATE_PIXELSHADER)) { + shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context); + } + } }
static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6111f53..20c9072 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1468,6 +1468,7 @@ typedef struct shader_reg_maps { /* Sampler usage tokens * Use 0 as default (bit 31 is always 1 on a valid token) */ DWORD samplers[MAX_SAMPLERS]; + char bumpmat;
/* Whether or not a loop is used in this shader */ char loop; @@ -1834,6 +1835,10 @@ typedef struct IWineD3DPixelShaderImpl { /* run time data */ PSHADERDATA *data;
+ /* Some information about the shader behavior */ + char needsbumpmat; + UINT bumpenvmatconst; + #if 0 /* needs reworking */ PSHADERINPUTDATA input; PSHADEROUTPUTDATA output;