diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 2f6c46a6fab..6a86132a1ff 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -799,11 +799,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, return temp_result; /* Otherwise, might as well set the whole state block to the appropriate values */ - if ( This->stateBlock != NULL) { - memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl)); - } else { - memset(object->streamFreq, 1, sizeof(object->streamFreq)); - } + if (This->stateBlock != NULL) + stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock); + else + memset(object->streamFreq, 1, sizeof(object->streamFreq)); /* Reset the ref and type after kludging it */ object->wineD3DDevice = This; @@ -815,11 +814,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, if (Type == WINED3DSBT_ALL) { TRACE("ALL => Pretend everything has changed\n"); - memset(&object->changed, TRUE, sizeof(This->stateBlock->changed)); + stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE); + } else if (Type == WINED3DSBT_PIXELSTATE) { TRACE("PIXELSTATE => Pretend all pixel shates have changed\n"); - memset(&object->changed, FALSE, sizeof(This->stateBlock->changed)); + stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE); object->changed.pixelShader = TRUE; @@ -849,7 +849,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, } else if (Type == WINED3DSBT_VERTEXSTATE) { TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n"); - memset(&object->changed, FALSE, sizeof(This->stateBlock->changed)); + stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE); object->changed.vertexShader = TRUE; diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 62d681b0da8..067fe4e616f 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -208,10 +208,6 @@ static void select_shader_mode( int* ps_selected, int* vs_selected) { - /* Default # of constants to 0 */ - gl_info->max_vshader_constantsF = 0; - gl_info->max_pshader_constantsF = 0; - /* Give priority to user disable/emulation request. * Then respect REF device for software. * Then check capabilities for hardware, and fallback to software */ @@ -222,12 +218,8 @@ static void select_shader_mode( *vs_selected = SHADER_SW; } else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested) { *vs_selected = SHADER_GLSL; - /* Subtract the other potential uniforms from the max available (bools & ints) */ - gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) { *vs_selected = SHADER_ARB; - /* ARB shaders seem to have an implicit PARAM when fog is used, so we need to subtract 1 from the total available */ - gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 1; } else { *vs_selected = SHADER_SW; } @@ -239,16 +231,50 @@ static void select_shader_mode( *ps_selected = SHADER_NONE; } else if (gl_info->supported[ARB_SHADING_LANGUAGE_100] && wined3d_settings.glslRequested) { *ps_selected = SHADER_GLSL; - /* Subtract the other potential uniforms from the max available (bools & ints) */ - gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) { *ps_selected = SHADER_ARB; - gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF; } else { *ps_selected = SHADER_NONE; } } +/** Select the number of report maximum shader constants based on the selected shader modes */ +void select_shader_max_constants(WineD3D_GL_Info *gl_info) { + + switch (wined3d_settings.vs_selected_mode) { + case SHADER_GLSL: + /* Subtract the other potential uniforms from the max available (bools & ints) */ + gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; + break; + case SHADER_ARB: + /* ARB shaders seem to have an implicit PARAM when fog is used, so we need to subtract 1 from the total available */ + gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 1; + break; + case SHADER_SW: + gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */ + break; + default: + gl_info->max_vshader_constantsF = 0; + break; + } + + switch (wined3d_settings.ps_selected_mode) { + case SHADER_GLSL: + /* Subtract the other potential uniforms from the max available (bools & ints) */ + gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I; + break; + case SHADER_ARB: + gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF; + break; + case SHADER_SW: + gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */ + break; + default: + gl_info->max_pshader_constantsF = 0; + break; + } +} + /********************************************************** * IWineD3D parts follows **********************************************************/ @@ -1609,6 +1635,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, } select_shader_mode(&This->gl_info, DeviceType, &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode); + select_shader_max_constants(&This->gl_info); /* ------------------------------------------------ The following fields apply to both d3d8 and d3d9 @@ -1995,6 +2022,7 @@ static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, LEAVE_GL(); select_shader_mode(&This->gl_info, DeviceType, &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode); + select_shader_max_constants(&This->gl_info); temp_result = allocate_shader_constants(object->updateStateBlock); if (WINED3D_OK != temp_result) diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index e3d0e7cc42f..85697f4a839 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -58,6 +58,140 @@ HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) { return WINED3D_OK; } +/** Copy all members of one stateblock to another */ +void stateblock_savedstates_copy( + IWineD3DStateBlock* iface, + SAVEDSTATES* dest, + SAVEDSTATES* source) { + + IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; + unsigned bsize = sizeof(BOOL); + + /* Single values */ + dest->indices = source->indices; + dest->material = source->material; + dest->fvf = source->fvf; + dest->viewport = source->viewport; + dest->vertexDecl = source->vertexDecl; + dest->pixelShader = source->pixelShader; + dest->vertexShader = source->vertexShader; + + /* Fixed size arrays */ + memcpy(dest->streamSource, source->streamSource, bsize * MAX_STREAMS); + memcpy(dest->streamFreq, source->streamFreq, bsize * MAX_STREAMS); + memcpy(dest->textures, source->textures, bsize * MAX_SAMPLERS); + memcpy(dest->transform, source->transform, bsize * (HIGHEST_TRANSFORMSTATE + 1)); + memcpy(dest->renderState, source->renderState, bsize * (WINEHIGHEST_RENDER_STATE + 1)); + memcpy(dest->textureState, source->textureState, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)); + memcpy(dest->samplerState, source->samplerState, bsize * MAX_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1)); + memcpy(dest->clipplane, source->clipplane, bsize * MAX_CLIPPLANES); + memcpy(dest->pixelShaderConstantsB, source->pixelShaderConstantsB, bsize * MAX_CONST_B); + memcpy(dest->pixelShaderConstantsI, source->pixelShaderConstantsI, bsize * MAX_CONST_I); + memcpy(dest->vertexShaderConstantsB, source->vertexShaderConstantsB, bsize * MAX_CONST_B); + memcpy(dest->vertexShaderConstantsI, source->vertexShaderConstantsI, bsize * MAX_CONST_I); + + /* Dynamically sized arrays */ + memcpy(dest->pixelShaderConstantsF, source->pixelShaderConstantsF, bsize * GL_LIMITS(pshader_constantsF)); + memcpy(dest->vertexShaderConstantsF, source->vertexShaderConstantsF, bsize * GL_LIMITS(vshader_constantsF)); +} + +/** Set all members of a stateblock savedstate to the given value */ +void stateblock_savedstates_set( + IWineD3DStateBlock* iface, + SAVEDSTATES* states, + BOOL value) { + + IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)iface; + unsigned bsize = sizeof(BOOL); + + /* Single values */ + states->indices = value; + states->material = value; + states->fvf = value; + states->viewport = value; + states->vertexDecl = value; + states->pixelShader = value; + states->vertexShader = value; + + /* Fixed size arrays */ + memset(states->streamSource, value, bsize * MAX_STREAMS); + memset(states->streamFreq, value, bsize * MAX_STREAMS); + memset(states->textures, value, bsize * MAX_SAMPLERS); + memset(states->transform, value, bsize * (HIGHEST_TRANSFORMSTATE + 1)); + memset(states->renderState, value, bsize * (WINEHIGHEST_RENDER_STATE + 1)); + memset(states->textureState, value, bsize * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)); + memset(states->samplerState, value, bsize * MAX_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1)); + memset(states->clipplane, value, bsize * MAX_CLIPPLANES); + memset(states->pixelShaderConstantsB, value, bsize * MAX_CONST_B); + memset(states->pixelShaderConstantsI, value, bsize * MAX_CONST_I); + memset(states->vertexShaderConstantsB, value, bsize * MAX_CONST_B); + memset(states->vertexShaderConstantsI, value, bsize * MAX_CONST_I); + + /* Dynamically sized arrays */ + memset(states->pixelShaderConstantsF, value, bsize * GL_LIMITS(pshader_constantsF)); + memset(states->vertexShaderConstantsF, value, bsize * GL_LIMITS(vshader_constantsF)); +} + +void stateblock_copy( + IWineD3DStateBlock* destination, + IWineD3DStateBlock* source) { + + IWineD3DStateBlockImpl *This = (IWineD3DStateBlockImpl *)source; + IWineD3DStateBlockImpl *Dest = (IWineD3DStateBlockImpl *)destination; + + /* IUnknown fields */ + Dest->lpVtbl = This->lpVtbl; + Dest->ref = This->ref; + + /* IWineD3DStateBlock information */ + Dest->parent = This->parent; + Dest->wineD3DDevice = This->wineD3DDevice; + Dest->blockType = This->blockType; + + /* Saved states */ + stateblock_savedstates_copy(source, &Dest->set, &This->set); + stateblock_savedstates_copy(source, &Dest->changed, &This->changed); + + /* Single items */ + Dest->fvf = This->fvf; + Dest->vertexDecl = This->vertexDecl; + Dest->vertexShader = This->vertexShader; + Dest->streamIsUP = This->streamIsUP; + Dest->pIndexData = This->pIndexData; + Dest->baseVertexIndex = This->baseVertexIndex; + Dest->lights = This->lights; + Dest->clip_status = This->clip_status; + Dest->viewport = This->viewport; + Dest->material = This->material; + Dest->pixelShader = This->pixelShader; + Dest->vertex_blend = This->vertex_blend; + Dest->tween_factor = This->tween_factor; + Dest->shaderPrgId = This->shaderPrgId; + + /* Fixed size arrays */ + memcpy(Dest->vertexShaderConstantB, This->vertexShaderConstantB, sizeof(BOOL) * MAX_CONST_B); + memcpy(Dest->vertexShaderConstantI, This->vertexShaderConstantI, sizeof(INT) * MAX_CONST_I * 4); + memcpy(Dest->pixelShaderConstantB, This->pixelShaderConstantB, sizeof(BOOL) * MAX_CONST_B); + memcpy(Dest->pixelShaderConstantI, This->pixelShaderConstantI, sizeof(INT) * MAX_CONST_I * 4); + + memcpy(Dest->streamStride, This->streamStride, sizeof(UINT) * MAX_STREAMS); + memcpy(Dest->streamOffset, This->streamOffset, sizeof(UINT) * MAX_STREAMS); + memcpy(Dest->streamSource, This->streamSource, sizeof(IWineD3DVertexBuffer*) * MAX_STREAMS); + memcpy(Dest->streamFreq, This->streamFreq, sizeof(UINT) * MAX_STREAMS); + memcpy(Dest->streamFlags, This->streamFlags, sizeof(UINT) * MAX_STREAMS); + memcpy(Dest->transforms, This->transforms, sizeof(D3DMATRIX) * (HIGHEST_TRANSFORMSTATE + 1)); + memcpy(Dest->clipplane, This->clipplane, sizeof(double) * MAX_CLIPPLANES * 4); + memcpy(Dest->renderState, This->renderState, sizeof(DWORD) * (WINEHIGHEST_RENDER_STATE + 1)); + memcpy(Dest->textures, This->textures, sizeof(IWineD3DBaseTexture*) * MAX_SAMPLERS); + memcpy(Dest->textureDimensions, This->textureDimensions, sizeof(int) * MAX_SAMPLERS); + memcpy(Dest->textureState, This->textureState, sizeof(DWORD) * MAX_TEXTURES * (WINED3D_HIGHEST_TEXTURE_STATE + 1)); + memcpy(Dest->samplerState, This->samplerState, sizeof(DWORD) * MAX_SAMPLERS * (WINED3D_HIGHEST_SAMPLER_STATE + 1)); + + /* Dynamically sized arrays */ + memcpy(Dest->vertexShaderConstantF, This->vertexShaderConstantF, sizeof(float) * GL_LIMITS(vshader_constantsF) * 4); + memcpy(Dest->pixelShaderConstantF, This->pixelShaderConstantF, sizeof(float) * GL_LIMITS(pshader_constantsF) * 4); +} + /********************************************************** * IWineD3DStateBlockImpl IUnknown parts follows **********************************************************/ @@ -654,7 +788,7 @@ should really perform a delta so that only the changes get updated*/ } else { FIXME("Unrecognized state block type %d\n", This->blockType); } - memcpy(&((IWineD3DDeviceImpl*)pDevice)->stateBlock->changed, &This->changed, sizeof(((IWineD3DDeviceImpl*)pDevice)->stateBlock->changed)); + stateblock_savedstates_copy(iface, &((IWineD3DDeviceImpl*)pDevice)->stateBlock->changed, &This->changed); TRACE("(%p) : Applied state block %p ------------------^\n", This, pDevice); return WINED3D_OK; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index dc0644dc037..d542086daca 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1113,6 +1113,20 @@ struct IWineD3DStateBlockImpl GLhandleARB shaderPrgId; }; +extern void stateblock_savedstates_set( + IWineD3DStateBlock* iface, + SAVEDSTATES* states, + BOOL value); + +extern void stateblock_savedstates_copy( + IWineD3DStateBlock* iface, + SAVEDSTATES* dest, + SAVEDSTATES* source); + +extern void stateblock_copy( + IWineD3DStateBlock* destination, + IWineD3DStateBlock* source); + extern const IWineD3DStateBlockVtbl IWineD3DStateBlock_Vtbl; /*****************************************************************************