Moved support for non power 2 texture to hardware.

Fix for the texture state separation patches, ApplyTextureStates is
now called instead of being commented out.
This commit is contained in:
Oliver Stieber 2005-08-03 19:49:05 +00:00 committed by Alexandre Julliard
parent aab700d16e
commit e31bc6cea4
7 changed files with 133 additions and 59 deletions

View File

@ -287,7 +287,7 @@ HRESULT WINAPI IWineD3DBaseTextureImpl_BindTexture(IWineD3DBaseTexture *iface) {
}
glBindTexture(textureDimensions, This->baseTexture.textureName);
checkGLcall("glBindTexture");
if (isNewTexture || (TRUE && This->baseTexture.levels >1)) {
if (isNewTexture) {
/* For a new texture we have to set the textures levels after binding the texture,
* in theory this is all we should ever have to dom, but because ATI's drivers are broken we
* also need to set the texture dimensins before the texture is is set */

View File

@ -220,7 +220,38 @@ UINT WINAPI IWineD3DCubeTextureImpl_GetTextureDimensions(IWineD3DCubeTexture *if
void WINAPI IWineD3DCubeTextureImpl_ApplyStateChanges(IWineD3DCubeTexture *iface,
const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface;
float matrix[16];
IWineD3DBaseTextureImpl_ApplyStateChanges((IWineD3DBaseTexture *)iface, textureStates, samplerStates);
/* Apply non-power2 mappings and texture offsets so long as the texture coords aren't projected or generated */
if(This->pow2scalingFactor != 1.0f) {
if((textureStates[WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) == D3DTSS_TCI_PASSTHRU && (~textureStates[WINED3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
glMatrixMode(GL_TEXTURE);
memset(matrix, 0 , sizeof(matrix));
matrix[0] = This->pow2scalingFactor;
matrix[5] = This->pow2scalingFactor;
matrix[10] = This->pow2scalingFactor;
#if 0 /* Translation fixup is no longer required (here for reminder) */
matrix[12] = -0.25f / (float)This->edgeLength;
matrix[13] = -0.75f / (float)This->edgeLength;
matrix[14] = -0.25f / (float)This->edgeLength;
#endif
TRACE("(%p) Setup Matrix:\n", This);
TRACE(" %f %f %f %f\n", matrix[0], matrix[1], matrix[2], matrix[3]);
TRACE(" %f %f %f %f\n", matrix[4], matrix[5], matrix[6], matrix[7]);
TRACE(" %f %f %f %f\n", matrix[8], matrix[9], matrix[10], matrix[11]);
TRACE(" %f %f %f %f\n", matrix[12], matrix[13], matrix[14], matrix[15]);
TRACE("\n");
glMultMatrixf(matrix);
} else {
/* I don't expect nonpower 2 textures to be used with generated texture coordinates, but if they are present a fixme. */
FIXME("Non-power2 texture being used with generated texture coords\n");
}
}
}

View File

@ -615,13 +615,13 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid
*********************************/
if (Format == WINED3DFMT_DXT1) {
/* DXT1 is half byte per pixel */
Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4)) >> 1;
} else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
} else {
Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
}
/** Create the and initilise surface resource **/
@ -652,11 +652,6 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid
/** TODO: change this into a texture transform matrix so that it's processed in hardware **/
/* Precalculated scaling for 'faked' non power of two texture coords */
object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
/** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
@ -716,6 +711,9 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Wid
UINT tmpW;
UINT tmpH;
HRESULT hr;
unsigned int pow2Width = Width;
unsigned int pow2Height = Height;
TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
@ -723,7 +721,19 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Wid
D3DINITILIZEBASETEXTURE(object->baseTexture);
object->width = Width;
object->height = Height;
/** Non-power2 support **/
/* Find the nearest pow2 match */
pow2Width = pow2Height = 1;
while (pow2Width < Width) pow2Width <<= 1;
while (pow2Height < Height) pow2Height <<= 1;
/** FIXME: add support for real non-power-two if it's provided by the video card **/
/* Precalculated scaling for 'faked' non power of two texture coords */
object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
/* Calculate levels for mip mapping */
if (Levels == 0) {
TRACE("calculating levels %d\n", object->baseTexture.levels);
@ -820,8 +830,11 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
/* Create the volume */
D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
(IWineD3DVolume **)&object->volumes[i], pSharedHandle);
/* Set it's container to this object */
IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
/* calcualte the next mipmap level */
tmpW = max(1, tmpW >> 1);
tmpH = max(1, tmpH >> 1);
tmpD = max(1, tmpD >> 1);
@ -856,8 +869,9 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
object->lockable = TRUE;
object->locked = FALSE;
memset(&object->lockedBox, 0, sizeof(D3DBOX));
object->dirty = FALSE;
return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
object->dirty = TRUE;
return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
}
HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
@ -867,29 +881,40 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT
HANDLE* pSharedHandle, IUnknown *parent,
D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
unsigned int i,j;
UINT tmpW;
HRESULT hr;
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
unsigned int i,j;
UINT tmpW;
HRESULT hr;
unsigned int pow2EdgeLength = EdgeLength;
D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
D3DINITILIZEBASETEXTURE(object->baseTexture);
D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
D3DINITILIZEBASETEXTURE(object->baseTexture);
TRACE("(%p) Create Cube Texture \n", This);
TRACE("(%p) Create Cube Texture \n", This);
object->edgeLength = EdgeLength;
object->edgeLength = EdgeLength;
/* Calculate levels for mip mapping */
if (Levels == 0) {
object->baseTexture.levels++;
tmpW = EdgeLength;
while (tmpW > 1) {
tmpW = max(1, tmpW / 2);
object->baseTexture.levels++;
}
TRACE("Calculated levels = %d\n", object->baseTexture.levels);
}
/** Non-power2 support **/
/* Find the nearest pow2 match */
pow2EdgeLength = 1;
while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
/* TODO: support for native non-power 2 */
/* Precalculated scaling for 'faked' non power of two texture coords */
object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
/* Calculate levels for mip mapping */
if (Levels == 0) {
object->baseTexture.levels++;
tmpW = EdgeLength;
while (tmpW > 1) {
tmpW = max(1, tmpW / 2);
object->baseTexture.levels++;
}
TRACE("Calculated levels = %d\n", object->baseTexture.levels);
}
/* Generate all the surfaces */
tmpW = EdgeLength;

View File

@ -1216,12 +1216,6 @@ static void drawStridedSlow(IWineD3DDevice *iface, Direct3DVertexStridedData *sd
}
}
/* crude support for non-power2 textures */
if (((IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->nonpow2) {
t *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorY;
s *= ((IWineD3DSurfaceImpl *)((IWineD3DTextureImpl *)This->stateBlock->textures[textureNo])->surfaces[0])->pow2scalingFactorX;
}
switch (coordsToUse) { /* Supply the provided texture coords */
case D3DTTFF_COUNT1:
VTRACE(("tex:%d, s=%f\n", textureNo, s));
@ -1578,9 +1572,9 @@ void inline drawPrimitiveTraceDataLocations(Direct3DVertexStridedData *dataLocat
}
/* loads any dirty textures and returns true if any of the textures are nonpower2 */
BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
BOOL nonPower2 = FALSE;
/* uploads textures and setup texture states ready for rendering */
void inline drawPrimitiveUploadTextures(IWineD3DDeviceImpl* This) {
unsigned int i;
/**
* OK, here we clear down any old junk iect in the context
@ -1606,14 +1600,6 @@ BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
/* 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]);
@ -1642,9 +1628,9 @@ BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
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 */
/* Tell the abse texture to sync it's states */
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 {
@ -1677,7 +1663,6 @@ BOOL inline drawPrimitiveUploadDirtyTextures(IWineD3DDeviceImpl* This) {
}
return nonPower2;
}
/* Routine common to the draw primitive and draw indexed primitive routines */
@ -1702,7 +1687,6 @@ void drawPrimitive(IWineD3DDevice *iface,
BOOL isLightingOn = FALSE;
Direct3DVertexStridedData dataLocations;
int useHW = FALSE;
BOOL nonPower2 = FALSE; /* set to true if any surfaces are non-power2 so that drawslow is used. */
if (This->stateBlock->vertexDecl == NULL) {
/* Work out what the FVF should look like */
@ -1795,7 +1779,7 @@ void drawPrimitive(IWineD3DDevice *iface,
/* Now initialize the materials state */
init_materials(iface, (dataLocations.u.s.diffuse.lpData != NULL));
nonPower2 = drawPrimitiveUploadDirtyTextures(This);
drawPrimitiveUploadTextures(This);
/* Now draw the graphics to the screen */
if (useVertexShaderFunction) {
@ -1820,7 +1804,6 @@ void drawPrimitive(IWineD3DDevice *iface,
} else if ((dataLocations.u.s.pSize.lpData != NULL)
|| (dataLocations.u.s.diffuse.lpData != NULL)
|| nonPower2
/*|| (dataLocations.u.s.blendWeights.lpData != NULL)*/) {
/* Fixme, Ideally, only use the per-vertex code for software HAL

View File

@ -23,7 +23,7 @@
#include "config.h"
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DEFAULT_DEBUG_CHANNEL(d3d_texture);
#define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
/* *******************************************
@ -70,8 +70,9 @@ ULONG WINAPI IWineD3DTextureImpl_Release(IWineD3DTexture *iface) {
IUnknown_Release(surfaceParent);
}
}
TRACE("(%p) : cleaning up base texture \n", This);
IWineD3DBaseTextureImpl_CleanUp((IWineD3DBaseTexture *)iface);
/* free the object */
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
@ -202,7 +203,39 @@ UINT WINAPI IWineD3DTextureImpl_GetTextureDimensions(IWineD3DTexture *iface) {
void WINAPI IWineD3DTextureImpl_ApplyStateChanges(IWineD3DTexture *iface,
const DWORD textureStates[WINED3D_HIGHEST_TEXTURE_STATE + 1],
const DWORD samplerStates[WINED3D_HIGHEST_SAMPLER_STATE + 1]) {
IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface;
float matrix[16];
IWineD3DBaseTextureImpl_ApplyStateChanges((IWineD3DBaseTexture *)iface, textureStates, samplerStates);
/** non-power2 fixups using texture matrix **/
if(This->pow2scalingFactorX != 1.0f || This->pow2scalingFactorY != 1.0f) {
/* Apply non-power2 mappings and texture offsets so long as the texture coords aren't projected or generated */
if(((textureStates[WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) == D3DTSS_TCI_PASSTHRU) &&
(~textureStates[WINED3DTSS_TEXTURETRANSFORMFLAGS] & D3DTTFF_PROJECTED)) {
glMatrixMode(GL_TEXTURE);
memset(matrix, 0 , sizeof(matrix));
matrix[0] = This->pow2scalingFactorX;
matrix[5] = This->pow2scalingFactorY;
#if 0 /* this isn't needed any more, I changed the translation in drawprim.c to 0.9/width instead of 1/width and everything lines up ok. left here as a reminder */
matrix[12] = -0.25f / (float)This->width;
matrix[13] = -0.75f / (float)This->height;
#endif
matrix[10] = 1;
matrix[15] = 1;
TRACE("(%p) Setup Matrix:\n", This);
TRACE(" %f %f %f %f\n", matrix[0], matrix[1], matrix[2], matrix[3]);
TRACE(" %f %f %f %f\n", matrix[4], matrix[5], matrix[6], matrix[7]);
TRACE(" %f %f %f %f\n", matrix[8], matrix[9], matrix[10], matrix[11]);
TRACE(" %f %f %f %f\n", matrix[12], matrix[13], matrix[14], matrix[15]);
TRACE("\n");
glMultMatrixf(matrix);
} else {
/* I don't expect nonpower 2 textures to be used with generated texture coordinates, but if they are present a fixme. */
FIXME("Non-power2 texture being used with generated texture coords\n");
}
}
}
/* *******************************************

View File

@ -1484,9 +1484,6 @@ void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords)
if (flags & D3DTTFF_PROJECTED) {
switch (flags & ~D3DTTFF_PROJECTED) {
case D3DTTFF_COUNT1:
mat[9] = 0;
break;
case D3DTTFF_COUNT2:
mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
mat[1] = mat[5] = mat[9] = mat[13] = 0;

View File

@ -690,6 +690,8 @@ typedef struct IWineD3DTextureImpl
UINT width;
UINT height;
float pow2scalingFactorX;
float pow2scalingFactorY;
} IWineD3DTextureImpl;
@ -709,6 +711,7 @@ typedef struct IWineD3DCubeTextureImpl
IWineD3DSurface *surfaces[6][MAX_LEVELS];
UINT edgeLength;
float pow2scalingFactor;
} IWineD3DCubeTextureImpl;
@ -790,9 +793,11 @@ struct IWineD3DSurfaceImpl
UINT pow2Height;
UINT pow2Size;
#if 0
/* precalculated x and y scalings for texture coords */
float pow2scalingFactorX; /* = (Width / pow2Width ) */
float pow2scalingFactorY; /* = (Height / pow2Height) */
#endif
BOOL lockable;
BOOL discard;