wined3d: Move samplers to the state table.

This commit is contained in:
Stefan Dösinger 2006-12-19 23:26:39 +01:00 committed by Alexandre Julliard
parent 2d1aeb4382
commit 666b507766
5 changed files with 131 additions and 152 deletions

View File

@ -3401,6 +3401,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface,
return WINED3D_OK;
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
return WINED3D_OK;
}
@ -3681,6 +3683,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, I
if (NULL != pShader) {
IWineD3DPixelShader_AddRef(pShader);
if(oldShader == NULL) {
/* Fixed function color ops deactivate the texture dimensions from the first stage which has colorop = disable
* Pixel shaders require that this is enabled, so dirtify all samplers, they will enable the dimensions.
* do not dirtify the colorop - it won't do anything when a ashader is bound
* This is temporary until pixel shaders are handled by the state table too
*/
int i;
for(i = 0; i < MAX_SAMPLERS; i++) {
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
}
}
}
if (NULL != oldShader) {
IWineD3DPixelShader_Release(oldShader);
@ -4471,6 +4484,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
return WINED3DERR_INVALIDCALL;
}
This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
}
oldTexture = This->updateStateBlock->textures[Stage];
@ -4493,6 +4507,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
* This means we should pass the refcount up to the parent
*******************************/
if (NULL != This->updateStateBlock->textures[Stage]) {
IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
if(oldTexture == NULL) {
/* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
@ -4501,22 +4518,39 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
}
if(bindCount == 1) {
new->baseTexture.sampler = Stage;
}
/* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
}
if (NULL != oldTexture) {
IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
IWineD3DBaseTexture_Release(oldTexture);
if(pTexture == NULL) {
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
}
if(bindCount && old->baseTexture.sampler == Stage) {
int i;
/* Have to do a search for the other sampler(s) where the texture is bound to
* Shouldn't happen as long as apps bind a texture only to one stage
*/
TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
if(This->updateStateBlock->textures[i] == oldTexture) {
old->baseTexture.sampler = i;
break;
}
}
}
}
/* Color keying is affected by the texture. Temporarily mark the color key state (=alpha test)
* dirty until textures are integrated with the state management
*/
if(Stage == 0 && This->stateBlock->renderState[WINED3DRS_COLORKEYENABLE]) {
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_COLORKEYENABLE));
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
return WINED3D_OK;
}

View File

@ -1845,126 +1845,6 @@ inline void drawPrimitiveTraceDataLocations(
}
static void drawPrimitiveUploadTexturesPS(IWineD3DDeviceImpl* This) {
INT i;
for (i = 0; i < GL_LIMITS(samplers); ++i) {
/* Pixel shader support should imply multitexture support. */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
checkGLcall("glActiveTextureARB");
} else if (i) {
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
if (!This->stateBlock->textures[i]) continue;
/* Enable the correct target. Is this required for GLSL? For ARB_fragment_program it isn't, afaik. */
glDisable(GL_TEXTURE_1D);
This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
switch(This->stateBlock->textureDimensions[i]) {
case GL_TEXTURE_2D:
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
break;
case GL_TEXTURE_3D:
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
glDisable(GL_TEXTURE_2D);
break;
case GL_TEXTURE_CUBE_MAP_ARB:
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
break;
}
glEnable(This->stateBlock->textureDimensions[i]);
/* Upload texture, apply states */
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, i, REAPPLY_ALPHAOP);
IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
}
}
/* uploads textures and setup texture states ready for rendering */
static void drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
INT current_sampler = 0;
float constant_color[4];
unsigned int i;
/* ARB_texture_env_combine is limited to GL_MAX_TEXTURE_UNITS stages. On
* nVidia cards GL_MAX_TEXTURE_UNITS is generally not larger than 4.
* Register combiners however provide up to 8 combiner stages. In order to
* take advantage of this, we need to be separate D3D texture stages from
* GL texture units. When using register combiners GL_MAX_TEXTURE_UNITS
* corresponds to MaxSimultaneousTextures and GL_MAX_GENERAL_COMBINERS_NV
* corresponds to MaxTextureBlendStages in the caps. */
if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], constant_color);
GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &constant_color[0]));
}
for (i = 0; i < GL_LIMITS(texture_stages); ++i) {
INT texture_idx = -1;
/* WINED3DTOP_DISABLE disables the current & any higher texture stages */
if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) break;
if (/*!GL_SUPPORT(NV_REGISTER_COMBINERS) || This->stateBlock->textures[i]*/ TRUE) {
texture_idx = current_sampler++;
/* Active the texture unit corresponding to the current texture stage */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
checkGLcall("glActiveTextureARB");
} else if (i) {
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
}
if (This->stateBlock->textures[i]) {
/* Enable the correct target. This has to stay here until samplers are moved over to the state table */
glDisable(GL_TEXTURE_1D);
This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
switch(This->stateBlock->textureDimensions[i]) {
case GL_TEXTURE_2D:
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
break;
case GL_TEXTURE_3D:
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
glDisable(GL_TEXTURE_2D);
break;
case GL_TEXTURE_CUBE_MAP_ARB:
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
break;
}
/* imply GL_SUPPORT(NV_TEXTURE_SHADER) when setting texture_shader_active */
if (This->texture_shader_active && This->stateBlock->textureDimensions[i] == GL_TEXTURE_2D) {
glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
} else {
glEnable(This->stateBlock->textureDimensions[i]);
}
/* Upload texture, apply states */
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, texture_idx, REAPPLY_ALPHAOP);
IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
} else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
/* ARB_texture_env_combine needs a valid texture bound to the
* texture unit, even if it isn't used. Bind a dummy texture. */
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
glEnable(GL_TEXTURE_1D);
This->stateBlock->textureDimensions[i] = GL_TEXTURE_1D;
glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[i]);
}
}
}
static void check_fbo_status(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
@ -2170,12 +2050,6 @@ void drawPrimitive(IWineD3DDevice *iface,
/* Now initialize the materials state */
init_materials(iface, (dataLocations->u.s.diffuse.lpData != NULL || dataLocations->u.s.diffuse.VBO != 0));
if (usePixelShaderFunction) {
drawPrimitiveUploadTexturesPS(This);
} else {
drawPrimitiveUploadTextures(This);
}
{
GLenum glPrimType;
/* Ok, Work out which primitive is requested and how many vertexes that

View File

@ -517,6 +517,8 @@ static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock) {
glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
}
} else {
GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
}
}
@ -1647,6 +1649,64 @@ static void tex_resultarg(DWORD state, IWineD3DStateBlockImpl *stateblock) {
}
}
static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock) {
DWORD sampler = state - STATE_SAMPLER(0);
TRACE("Sampler: %d\n", sampler);
/* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
* only has to bind textures and set the per texture states
*/
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
/* TODO: register combiners! */
if(sampler >= GL_LIMITS(sampler_stages)) {
return;
}
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + sampler));
checkGLcall("glActiveTextureARB");
} else if (sampler > 0) {
/* We can't do anything here */
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
return;
}
if(stateblock->textures[sampler]) {
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) stateblock->textures[sampler]);
IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)stateblock->wineD3DDevice, sampler, sampler, REAPPLY_ALPHAOP);
IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
if (stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader &&
((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function) {
/* Using a pixel shader? Verify the sampler types */
/* Make sure that the texture dimensions are enabled. I don't have to disable the other
* dimensions because the shader knows from which texture type to sample from. For the sake of
* debugging all dimensions could be enabled and a texture with some ugly pink bound to the unused
* dimensions. This should make wrong sampling sources visible :-)
*/
glEnable(stateblock->textureDimensions[sampler]);
checkGLcall("glEnable(stateblock->textureDimensions[sampler])");
} else if(sampler < stateblock->lowest_disabled_stage) {
activate_dimensions(sampler, stateblock);
if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
/* If color keying is enabled update the alpha test, it depends on the existance
* of a color key in stage 0
*/
state_alpha(WINED3DRS_COLORKEYENABLE, stateblock);
}
}
} else if(sampler < GL_LIMITS(texture_stages)) {
if(sampler < stateblock->lowest_disabled_stage) {
/* TODO: Check if the colorop is dirty to do that job
* TODO: What should I do with pixel shaders here ???
*/
activate_dimensions(sampler, stateblock);
} /* Otherwise tex_colorop disables the stage */
glBindTexture(GL_TEXTURE_1D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
checkGLcall("glBindTexture(GL_TEXTURE_1D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
}
}
const struct StateEntry StateTable[] =
{
/* State name representative, apply function */
@ -2128,20 +2188,20 @@ const struct StateEntry StateTable[] =
{ /*7, 31, undefined */ 0 /* -> sampler state in ddraw / d3d8 */, state_undefined },
{ /*7, 32, WINED3DTSS_CONSTANT */ 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl },
/* Sampler states */
{ /* 0, Sampler 0 */ STATE_SAMPLER(0), state_undefined },
{ /* 1, Sampler 1 */ STATE_SAMPLER(1), state_undefined },
{ /* 2, Sampler 2 */ STATE_SAMPLER(2), state_undefined },
{ /* 3, Sampler 3 */ STATE_SAMPLER(3), state_undefined },
{ /* 4, Sampler 3 */ STATE_SAMPLER(4), state_undefined },
{ /* 5, Sampler 5 */ STATE_SAMPLER(5), state_undefined },
{ /* 6, Sampler 6 */ STATE_SAMPLER(6), state_undefined },
{ /* 7, Sampler 7 */ STATE_SAMPLER(7), state_undefined },
{ /* 8, Sampler 8 */ STATE_SAMPLER(8), state_undefined },
{ /* 9, Sampler 9 */ STATE_SAMPLER(9), state_undefined },
{ /*10, Sampler 10 */ STATE_SAMPLER(10), state_undefined },
{ /*11, Sampler 11 */ STATE_SAMPLER(11), state_undefined },
{ /*12, Sampler 12 */ STATE_SAMPLER(12), state_undefined },
{ /*13, Sampler 13 */ STATE_SAMPLER(13), state_undefined },
{ /*14, Sampler 14 */ STATE_SAMPLER(14), state_undefined },
{ /*15, Sampler 15 */ STATE_SAMPLER(15), state_undefined },
{ /* 0, Sampler 0 */ STATE_SAMPLER(0), sampler },
{ /* 1, Sampler 1 */ STATE_SAMPLER(1), sampler },
{ /* 2, Sampler 2 */ STATE_SAMPLER(2), sampler },
{ /* 3, Sampler 3 */ STATE_SAMPLER(3), sampler },
{ /* 4, Sampler 3 */ STATE_SAMPLER(4), sampler },
{ /* 5, Sampler 5 */ STATE_SAMPLER(5), sampler },
{ /* 6, Sampler 6 */ STATE_SAMPLER(6), sampler },
{ /* 7, Sampler 7 */ STATE_SAMPLER(7), sampler },
{ /* 8, Sampler 8 */ STATE_SAMPLER(8), sampler },
{ /* 9, Sampler 9 */ STATE_SAMPLER(9), sampler },
{ /*10, Sampler 10 */ STATE_SAMPLER(10), sampler },
{ /*11, Sampler 11 */ STATE_SAMPLER(11), sampler },
{ /*12, Sampler 12 */ STATE_SAMPLER(12), sampler },
{ /*13, Sampler 13 */ STATE_SAMPLER(13), sampler },
{ /*14, Sampler 14 */ STATE_SAMPLER(14), sampler },
{ /*15, Sampler 15 */ STATE_SAMPLER(15), sampler },
};

View File

@ -1119,10 +1119,17 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
}
if (0 == This->resource.usage) { /* classic surface */
/**
* nothing to do
* waiting to reload the surface via IDirect3DDevice8::UpdateTexture
IWineD3DBaseTextureImpl *impl;
/* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
* Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
* states need resetting
*/
if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
if(impl->baseTexture.bindCount) {
IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
}
IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
}
} else if (WINED3DUSAGE_RENDERTARGET & This->resource.usage) { /* render surfaces */
/****************************
@ -1158,6 +1165,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + tex));
checkGLcall("glActiveTextureARB");
}
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(tex));
glDisable(GL_TEXTURE_2D);
checkGLcall("glDisable GL_TEXTURE_2D");
glDisable(GL_TEXTURE_1D);
@ -1168,6 +1176,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB");
}
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
/* And back buffers are not blended. Disable the depth test,
that helps performance */
@ -2394,6 +2403,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
/* Unbind the old texture */
glBindTexture(GL_TEXTURE_2D, 0);
IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
/* We use texture unit 0 for blts */

View File

@ -798,7 +798,8 @@ typedef struct IWineD3DBaseTextureClass
UINT LOD;
WINED3DTEXTUREFILTERTYPE filterType;
DWORD states[MAX_WINETEXTURESTATES];
LONG bindCount;
DWORD sampler;
} IWineD3DBaseTextureClass;
typedef struct IWineD3DBaseTextureImpl