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:
parent
567f0314af
commit
9e6957bbdc
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue