From 5615513877c81d6602ebffad05c3af37e4951e2b Mon Sep 17 00:00:00 2001 From: Oliver Stieber Date: Mon, 1 Aug 2005 09:20:55 +0000 Subject: [PATCH] Separate the management of DirectX states and openGL states. --- dlls/wined3d/basetexture.c | 2 +- dlls/wined3d/device.c | 159 ++++++------------------------------- dlls/wined3d/drawprim.c | 113 +++++++++++++++++++++----- dlls/wined3d/stateblock.c | 3 +- 4 files changed, 121 insertions(+), 156 deletions(-) diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c index abdd4e2b3a8..904402a038a 100644 --- a/dlls/wined3d/basetexture.c +++ b/dlls/wined3d/basetexture.c @@ -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)"); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 586603b3982..6fe83ba35ad 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -254,11 +254,11 @@ void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD S of these, which is what the Flags allows */ case WINED3DTSS_COLOROP: case WINED3DTSS_TEXCOORDINDEX: - if (!(Flags == REAPPLY_ALL)) skip=TRUE; + if (!(Flags == REAPPLY_ALL)) skip = TRUE; break; case WINED3DTSS_ALPHAOP: - if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE; + if (!(Flags & REAPPLY_ALPHAOP)) skip = TRUE; break; default: @@ -266,25 +266,14 @@ 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]); } } /* apply the sampler states to the texture */ - for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE;i++) { - IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]); + for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE; i++) { + IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]); } /* Note the D3DRS value applies to all textures, but GL has one @@ -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,23 +4159,30 @@ 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; } - This->updateStateBlock->set.textures[Stage] = TRUE; + 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; - This->updateStateBlock->textures[Stage] = pTexture; + TRACE("(%p) : setting new texture to %p\n", This, pTexture); + This->updateStateBlock->textures[Stage] = pTexture; /* Handle recording of state blocks */ if (This->isRecordingState) { @@ -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. diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 8b73cb36cfa..3d6d56a1b6f 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -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 */ - 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); - } - if (IWineD3DResourceImpl_GetType((IWineD3DResource *)texture) == D3DRTYPE_TEXTURE) { - /* TODO: Is this right, as its cast all texture types to texture8... checkme */ - IWineD3DSurface *surface; - IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)texture, 0, &surface); - if (((IWineD3DSurfaceImpl *)surface)->nonpow2) { - nonPower2 = TRUE; - } - } + /* upload the textures */ + for (i = 0; i< GL_LIMITS(textures); ++i) { + /* 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"); } - } + + /* 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 *)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; } diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 60a51314b26..2828d81b3fe 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -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();