Optionally repack nonpower 2 textures to the expected span length when

a textures is locked. This is necessary for buggy games like Warhammer
40k that don't work with the odd span sizes produce by default
nonpower 2 support.
This commit is contained in:
Oliver Stieber 2005-09-23 11:08:03 +00:00 committed by Alexandre Julliard
parent 567f0314af
commit 9e6957bbdc
4 changed files with 149 additions and 48 deletions

View File

@ -716,7 +716,7 @@ HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Wid
Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
Size = ((max(pow2Width,4) * D3DFmtGetBpp(This, Format)) * max(pow2Height,4));
} else {
Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
Size = (pow2Width * D3DFmtGetBpp(This, Format)) * pow2Height;
}
/** Create the and initilise surface resource **/
@ -5161,21 +5161,35 @@ HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3
} else {
/* some applications cannot handle odd pitches returned by soft non-power2, so we have
to repack the data from pow2Width/Height to expected Width,Height, this makes the
data returned by GetData non-power2 width/height with hardware non-power2
pow2Width/height are set to surface width height, repacking isn't needed so it
doesn't matter which function gets called. */
glTexSubImage2D(glDescription->target
if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
/* some applications cannot handle odd pitches returned by soft non-power2, so we have
to repack the data from pow2Width/Height to expected Width,Height, this makes the
data returned by GetData non-power2 width/height with hardware non-power2
pow2Width/height are set to surface width height, repacking isn't needed so it
doesn't matter which function gets called. */
glTexSubImage2D(glDescription->target
,glDescription->level
,destLeft
,destTop
,srcWidth
,srcHeight
,glDescription->glFormat
,glDescription->glType
,IWineD3DSurface_GetData(pSourceSurface)
);
} else {
/* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
glTexSubImage2D(glDescription->target
,glDescription->level
,destLeft
,destTop
,srcWidth
,srcHeight
,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
,glDescription->glFormat
,glDescription->glType
,IWineD3DSurface_GetData(pSourceSurface)
);
}
}
}

View File

@ -284,8 +284,13 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
pLockedRect->Pitch = (This->currentDesc.Width >> 2) << 4;
else
pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
else {
if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
pLockedRect->Pitch = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
} else {
pLockedRect->Pitch = This->bytesPerPixel * This->pow2Width;
}
}
if (NULL == pRect) {
pLockedRect->pBits = This->resource.allocatedMemory;
@ -355,6 +360,65 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, D3DLOCKED_RE
This->glDescription.glType,
This->resource.allocatedMemory);
vcheckGLcall("glGetTexImage");
if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
/* some games (e.g. warhammer 40k) don't work with the odd pitchs properly, preventing
the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
repack the texture so that the bpp * width pitch can be used instead of the bpp * pow2width.
Were doing this...
instead of boxing the texture :
|<-texture width ->| -->pow2width| /\
|111111111111111111| | |
|222 Texture 222222| boxed empty | texture height
|3333 Data 33333333| | |
|444444444444444444| | \/
----------------------------------- |
| boxed empty | boxed empty | pow2height
| | | \/
-----------------------------------
were repacking the data to the expected texture width
|<-texture width ->| -->pow2width| /\
|111111111111111111222222222222222| |
|222333333333333333333444444444444| texture height
|444444 | |
| | \/
| | |
| empty | pow2height
| | \/
-----------------------------------
== is the same as
|<-texture width ->| /\
|111111111111111111|
|222222222222222222|texture height
|333333333333333333|
|444444444444444444| \/
--------------------
this also means that any references to allocatedMemory should work with the data as if were a standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
internally the texture is still stored in a boxed format so any references to textureName will get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
*/
if (This->nonpow2) {
BYTE* dataa, *datab;
int pitcha = 0, pitchb = 0;
int y;
pitcha = This->bytesPerPixel * This->currentDesc.Width;
pitchb = This->bytesPerPixel * This->pow2Width;
datab = dataa = This->resource.allocatedMemory;
FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, pitcha, pitchb);
for (y = 1 ; y < This->currentDesc.Height; y++) {
dataa += pitcha; /* skip the first row */
datab += pitchb;
memcpy(dataa, datab, pitcha);
}
}
}
}
LEAVE_GL();
} else { /* Nothing to do */
@ -945,7 +1009,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
} else {
/* TODO: possibly use texture rectangle (though we are probably more compatible without it) */
if (This->nonpow2 == TRUE) {
if (NP2_REPACK == wined3d_settings.nonpower2_mode && This->nonpow2 == TRUE) {
TRACE("non power of two support\n");
ENTER_GL();
@ -997,8 +1062,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
This->glDescription.level,
debug_d3dformat(This->resource.format),
This->glDescription.glFormatInternal,
This->currentDesc.Width,
This->currentDesc.Height,
This->pow2Width,
This->pow2Height,
0,
This->glDescription.glFormat,
This->glDescription.glType,
@ -1008,8 +1073,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
glTexImage2D(This->glDescription.target,
This->glDescription.level,
This->glDescription.glFormatInternal,
This->currentDesc.Width,
This->currentDesc.Height,
This->pow2Width,
This->pow2Height,
0 /* border */,
This->glDescription.glFormat,
This->glDescription.glType,

View File

@ -113,24 +113,24 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
len = GetModuleFileNameA( 0, buffer, MAX_PATH );
if (len && len < MAX_PATH)
{
HKEY tmpkey;
/* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
{
char *p, *appname = buffer;
if ((p = strrchr( appname, '/' ))) appname = p + 1;
if ((p = strrchr( appname, '\\' ))) appname = p + 1;
strcat( appname, "\\Direct3D" );
TRACE("appname = [%s] \n", appname);
if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
RegCloseKey( tmpkey );
}
HKEY tmpkey;
/* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
{
char *p, *appname = buffer;
if ((p = strrchr( appname, '/' ))) appname = p + 1;
if ((p = strrchr( appname, '\\' ))) appname = p + 1;
strcat( appname, "\\Direct3D" );
TRACE("appname = [%s] \n", appname);
if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
RegCloseKey( tmpkey );
}
}
if ( 0 != hkey || 0 != appkey )
{
if ( !get_config_key( hkey, appkey, "VertexShaderMode", buffer, size) )
{
if ( !get_config_key( hkey, appkey, "VertexShaderMode", buffer, size) )
{
if (!strcmp(buffer,"none"))
{
TRACE("Disable vertex shaders\n");
@ -141,33 +141,48 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
TRACE("Force SW vertex shaders\n");
wined3d_settings.vs_mode = VS_SW;
}
}
if ( !get_config_key( hkey, appkey, "PixelShaderMode", buffer, size) )
{
}
if ( !get_config_key( hkey, appkey, "PixelShaderMode", buffer, size) )
{
if (!strcmp(buffer,"enabled"))
{
TRACE("Allow pixel shaders\n");
wined3d_settings.ps_mode = PS_HW;
}
if (!strcmp(buffer,"disabled"))
if (!strcmp(buffer,"disabled"))
{
TRACE("Disable pixel shaders\n");
wined3d_settings.ps_mode = PS_NONE;
}
}
if ( !get_config_key( hkey, appkey, "VertexBufferMode", buffer, size) )
{
}
if ( !get_config_key( hkey, appkey, "VertexBufferMode", buffer, size) )
{
if (!strcmp(buffer,"none"))
{
TRACE("Disable Vertex Buffer Hardware support\n");
wined3d_settings.vbo_mode = VS_NONE;
wined3d_settings.vbo_mode = VBO_NONE;
}
else if (!strcmp(buffer,"hardware"))
{
TRACE("Allow Vertex Buffer Hardware support\n");
wined3d_settings.vbo_mode = VS_HW;
TRACE("Allow Vertex Buffer Hardware support\n");
wined3d_settings.vbo_mode = VBO_HW;
}
}
}
if ( !get_config_key( hkey, appkey, "Nonpower2Mode", buffer, size) )
{
if (!strcmp(buffer,"none"))
{
TRACE("Using default non-power2 textures\n");
wined3d_settings.nonpower2_mode = NP2_NONE;
}
else if (!strcmp(buffer,"repack"))
{
TRACE("Repacking non-power2 textre\n");
wined3d_settings.nonpower2_mode = NP2_REPACK;
}
/* There will be a couple of other choices for nonpow2, they are: TextureRecrangle and OpenGL 2 */
}
}
if (wined3d_settings.vs_mode == VS_HW)
TRACE("Allow HW vertex shaders\n");
@ -175,6 +190,8 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
TRACE("Disable pixel shaders\n");
if (wined3d_settings.vbo_mode == VBO_NONE)
TRACE("Disable Vertex Buffer Hardware support\n");
if (wined3d_settings.nonpower2_mode == NP2_REPACK)
TRACE("Repacking non-power2 textures\n");
if (appkey) RegCloseKey( appkey );
if (hkey) RegCloseKey( hkey );

View File

@ -110,21 +110,26 @@ UINT static const glTypeLookup[D3DDECLTYPE_UNUSED][5] = {
/**
* Settings
*/
#define VS_NONE 0
#define VS_HW 1
#define VS_SW 2
#define VS_NONE 0
#define VS_HW 1
#define VS_SW 2
#define PS_NONE 0
#define PS_HW 1
#define PS_NONE 0
#define PS_HW 1
#define VBO_NONE 0
#define VBO_HW 1
#define VBO_NONE 0
#define VBO_HW 1
#define NP2_NONE 0
#define NP2_REPACK 1
typedef struct wined3d_settings_s {
/* vertex and pixel shader modes */
int vs_mode;
int ps_mode;
int vbo_mode;
/* nonpower 2 function */
int nonpower2_mode;
} wined3d_settings_t;
extern wined3d_settings_t wined3d_settings;