Separate the management of DirectX states and openGL states.

This commit is contained in:
Oliver Stieber 2005-08-01 09:20:55 +00:00 committed by Alexandre Julliard
parent b671180c6a
commit 5615513877
4 changed files with 121 additions and 156 deletions

View File

@ -233,7 +233,7 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
/* Always need to reset the number of mipmap levels when rebinding as it is
a property of the active texture unit, and another texture may have set it
to a different value */
if (This->baseTexture.levels > 0) {
if (This->baseTexture.levels > 1) {
TRACE("Setting GL_TEXTURE_MAX_LEVEL to %d\n", This->baseTexture.levels - 1);
glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels - 1);
checkGLcall("glTexParameteri(textureDimensions, GL_TEXTURE_MAX_LEVEL, This->baseTexture.levels)");

View File

@ -266,17 +266,6 @@ void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD S
}
if (skip == FALSE) {
/* Performance: Only change to this texture if we have to */
if (changeTexture) {
/* Make appropriate texture active */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GLACTIVETEXTURE(Stage);
} else if (Stage > 0) {
FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
changeTexture = FALSE;
}
/* Now apply the change */
IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
}
@ -1652,13 +1641,14 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANS
ENTER_GL();
if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
#if 0 /* This is now set with the texture unit states, it may be a good idea to flag the change though! */
if (d3dts < GL_LIMITS(textures)) {
int tex = d3dts - D3DTS_TEXTURE0;
GLACTIVETEXTURE(tex);
set_texture_matrix((float *)lpmatrix,
This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS], (This->stateBlock->textureState[tex][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
}
#endif
} else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
unsigned int k;
@ -4169,22 +4159,29 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage,
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DBaseTexture *oldTexture;
BOOL reapplyStates = TRUE;
DWORD reapplyFlags = 0;
INT oldTextureDimensions = -1;
D3DRESOURCETYPE textureType;
oldTexture = This->updateStateBlock->textures[Stage];
TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
/* Reject invalid texture units */
if (Stage >= GL_LIMITS(textures)) {
TRACE("Attempt to access invalid texture rejected\n");
#if 0 /* TODO: check so vertex textures */
if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
return D3D_OK;
}
#endif
if (Stage >= GL_LIMITS(textures) || Stage < 0) {
WARN("Attempt to access invalid texture rejected\n");
return D3DERR_INVALIDCALL;
}
oldTexture = This->updateStateBlock->textures[Stage];
TRACE("GL_LIMITS %d\n",GL_LIMITS(textures));
TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
This->updateStateBlock->set.textures[Stage] = TRUE;
This->updateStateBlock->changed.textures[Stage] = TRUE;
TRACE("(%p) : setting new texture to %p\n", This, pTexture);
This->updateStateBlock->textures[Stage] = pTexture;
/* Handle recording of state blocks */
@ -4193,18 +4190,6 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage,
return D3D_OK;
}
oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
ENTER_GL();
/* Make appropriate texture active */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GLACTIVETEXTURE(Stage);
} else if (Stage>0) {
FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
/** NOTE: MSDN says that setTexture increases the reference count,
* and the the application nust set the texture back to null (or have a leaky application),
* This means we should pass the refcount upto the parent
@ -4212,7 +4197,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage,
if (NULL != This->updateStateBlock->textures[Stage]) {
IUnknown *textureParent;
IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
/** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
/** NOTE: GetParent will increase the ref count for me, I won't clean up until the texture is set to NULL **/
}
if (NULL != oldTexture) {
@ -4223,102 +4208,6 @@ HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage,
oldTexture = NULL;
}
if (NULL != pTexture) {
/* Now setup the texture appropraitly */
textureType = IWineD3DBaseTexture_GetType(pTexture);
if (textureType == D3DRTYPE_TEXTURE) {
if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
TRACE("Skipping setting texture as old == new\n");
reapplyStates = FALSE;
} else {
/* Standard 2D texture */
TRACE("Standard 2d texture\n");
This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
/* Load up the texture now */
IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
}
} else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
TRACE("Skipping setting texture as old == new\n");
reapplyStates = FALSE;
} else {
/* Standard 3D (volume) texture */
TRACE("Standard 3d texture\n");
This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
/* Load up the texture now */
IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
}
} else if (textureType == D3DRTYPE_CUBETEXTURE) {
if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
TRACE("Skipping setting texture as old == new\n");
reapplyStates = FALSE;
} else {
/* Standard Cube texture */
TRACE("Standard Cube texture\n");
This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
/* Load up the texture now */
IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
}
} else {
FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
}
} else {
TRACE("Setting to no texture (ie default texture)\n");
This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
checkGLcall("glBindTexture");
TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
}
/* Disable the old texture binding and enable the new one (unless operations are disabled) */
if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
glDisable(oldTextureDimensions);
checkGLcall("Disable oldTextureDimensions");
if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
glEnable(This->updateStateBlock->textureDimensions[Stage]);
checkGLcall("glEnable new texture dimensions");
}
/* If Alpha arg1 is texture then handle the special case when there changes between a
texture and no texture - See comments in set_tex_op */
if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
(((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
{
reapplyFlags |= REAPPLY_ALPHAOP;
}
}
/* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
if (reapplyStates) {
IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
}
LEAVE_GL();
TRACE("Texture now fully setup\n");
return D3D_OK;
}
@ -5584,7 +5473,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
/** ****************************************
*GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
*GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
*they note:
* In future releases, we may provide the calls glXCreateNewContext,
* glXQueryDrawable and glXMakeContextCurrent.

View File

@ -1578,29 +1578,104 @@ void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocat
}
/* loads any dirty textures and returns true if any of the textures are nonpower2 */
/**
* OK, here we clear down any old junk iect in the context
* enable the new texture and apply any state changes:
*
* Loop through all textures
* select texture unit
* if there is a texture bound to that unit then..
* disable all textures types on that unit
* enable and bind the texture that is bound to that unit.
* otherwise dissable all texture types on that unit.
**/
BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
BOOL nonPower2 = FALSE;
unsigned int i;
register IWineD3DBaseTexture *texture;
/* And re-upload any dirty textures */
/* upload the textures */
for (i = 0; i< GL_LIMITS(textures); ++i) {
texture = This->stateBlock->textures[i];
if (texture != NULL) {
if(IWineD3DBaseTexture_GetDirty(texture)) {
/* Load up the texture now */
IWineD3DTexture_PreLoad((IWineD3DTexture *)texture);
/* Bind the texture to the stage here */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GLACTIVETEXTURE(i);
} else if (0 < i) {
/* This isn't so much a warn as a message to the user about lack of hardware support */
WARN("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
}
if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) {
/* TODO: Is this right, as its cast all texture types to texture8... checkme */
/* don't bother with textures that have a colorop of disable */
if (This->stateBlock->textureState[i][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
if (This->stateBlock->textures[i] != NULL) {
/* check to see if any of the texturs are non-power2 */
if (IWineD3DResourceImpl_GetType((IWineD3DResource *)This->stateBlock->textures[i]) == D3DRTYPE_TEXTURE) {
IWineD3DSurface *surface;
IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface);
IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)This->stateBlock->textures[i], 0, &surface);
if (((IWineD3DSurfaceImpl *)surface)->nonpow2) {
nonPower2 = TRUE;
}
}
glDisable(GL_TEXTURE_1D);
This->stateBlock->textureDimensions[i] = IWineD3DBaseTexture_GetTextureDimensions(This->stateBlock->textures[i]);
/* disable all texture states that aren't the selected textures' dimension */
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 GLTEXTURECUBEMAP:
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]);
}
/* Load up the texture now */
IWineD3DBaseTexture_PreLoad((IWineD3DBaseTexture *) This->stateBlock->textures[i]);
IWineD3DDevice_SetupTextureStates((IWineD3DDevice *)This, i, REAPPLY_ALPHAOP);
/* this is a stub function representing the state blocks being seperated here we are only updating the texture state changes, other objects and units get updated when they change (or need to be updated), e.g. states that relate to a context member line the texture unit are only updated when the context needs updating */
#if 0 /* TODO: move the setting of states over to base texture */
IWineD3DBaseTexture_ApplyStateChanges(This->stateBlock->textures[i], This->stateBlock->textureState[i], This->stateBlock->samplerState[i]);
#endif
}
/* Bind a default texture if no texture has been set, but colour-op is enabled */
else {
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]);
}
/** these ops apply to the texture unit, so they are preseved between texture changes, but for now brute force and reapply all
dx9_1pass_emboss_bump_mapping and dx9_2pass_emboss_bump_mapping are good texts to make sure the states are being applied when needed **/
set_tex_op((IWineD3DDevice *)This, FALSE, i, This->stateBlock->textureState[i][WINED3DTSS_COLOROP],
This->stateBlock->textureState[i][WINED3DTSS_COLORARG1],
This->stateBlock->textureState[i][WINED3DTSS_COLORARG2],
This->stateBlock->textureState[i][WINED3DTSS_COLORARG0]);
/* alphaop */
set_tex_op((IWineD3DDevice *)This, TRUE, i, This->stateBlock->textureState[i][WINED3DTSS_ALPHAOP],
This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG1],
This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG2],
This->stateBlock->textureState[i][WINED3DTSS_ALPHAARG0]);
} else {
/* no colorop so disable all the texture states */
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_3D);
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
}
}
return nonPower2;
}

View File

@ -728,9 +728,10 @@ HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStateBlock*
glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &white);
checkGLcall("glTexImage1D");
#if 1 /* TODO: move the setting texture states off to basetexture */
/* Reapply all the texture state information to this texture */
IWineD3DDevice_SetupTextureStates(device, i, REAPPLY_ALL);
#endif
}
LEAVE_GL();