wined3d: Always use np2 repacking if no native np2 support is available.

This commit is contained in:
Stefan Dösinger 2007-02-13 20:21:48 +01:00 committed by Alexandre Julliard
parent 21172f1dec
commit b48dfb3c54
7 changed files with 55 additions and 105 deletions

View File

@ -136,9 +136,9 @@ static void test_surface_alignment(IDirect3DDevice9 *device_ptr)
ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
ok(!(lockedRect.Pitch & 3), "Surface pitch %d is not 32-bit aligned\n", lockedRect.Pitch);
/* Some applications also depend on the exact pitch, rather than just
* the alignment. However, this test will fail or succeed depending
* on the NP2 mode we're using. */
if (0) ok(lockedRect.Pitch == 12, "Got pitch %d, expected 12\n", lockedRect.Pitch);
* the alignment.
*/
ok(lockedRect.Pitch == 12, "Got pitch %d, expected 12\n", lockedRect.Pitch);
hr = IDirect3DSurface9_UnlockRect(surface_ptr);
IDirect3DSurface9_Release(surface_ptr);
}

View File

@ -760,7 +760,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
*******************************/
/* Non-power2 support */
if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
pow2Width = Width;
pow2Height = Height;
} else {
@ -788,15 +788,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
Size = 0;
} else if (Format == WINED3DFMT_DXT1) {
/* DXT1 is half byte per pixel */
Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4)) >> 1;
Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
} else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
Size = ((max(pow2Width,4) * tableEntry->bpp) * max(pow2Height,4));
Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
} else {
/* The pitch is a multiple of 4 bytes */
Size = ((pow2Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
Size *= pow2Height;
Size = ((Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
Size *= Height;
}
/** Create and initialise the surface resource **/
@ -937,7 +937,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, U
object->height = Height;
/** Non-power2 support **/
if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
pow2Width = Width;
pow2Height = Height;
} else {
@ -5120,38 +5120,16 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface,
} else {
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
glTexSubImage2D(glDescription->target
,glDescription->level
,destLeft
,destTop
,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
,srcWidth
,srcHeight
,glDescription->glFormat
,glDescription->glType
,IWineD3DSurface_GetData(pSourceSurface)
);
}
}
}
checkGLcall("glTexSubImage2D");
@ -5632,6 +5610,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice*
}
void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
/* Reallocate proper memory for the front and back buffer and adjust their sizes */
if(surface->Flags & SFLAG_DIBSECTION) {
/* Release the DC */
@ -5645,7 +5625,7 @@ void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS*
}
surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
surface->pow2Width = *pPresentationParameters->BackBufferWidth;
surface->pow2Height = *pPresentationParameters->BackBufferHeight;
} else {

View File

@ -792,12 +792,6 @@ BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
* shaders), but 8 texture stages (register combiners). */
gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
/* We can only use NP2_NATIVE when the hardware supports it. */
if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
wined3d_settings.nonpower2_mode = NP2_NONE;
}
/* We can only use ORM_FBO when the hardware supports it. */
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");

View File

@ -1824,7 +1824,7 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont
* IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
* scaling is reapplied or removed, the texture matrix has to be reapplied
*/
if(wined3d_settings.nonpower2_mode != NP2_NATIVE && sampler < MAX_TEXTURES) {
if(!GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) && sampler < MAX_TEXTURES) {
if(stateblock->textureDimensions[sampler] == GL_TEXTURE_2D) {
if(((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorX != 1.0 ||
((IWineD3DTextureImpl *) stateblock->textures[sampler])->pow2scalingFactorY != 1.0 ) {

View File

@ -67,18 +67,33 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) {
LEAVE_GL();
}
} else {
void *mem;
int src_pitch = 0;
int dst_pitch = 0;
if (This->Flags & SFLAG_NONPOW2) {
src_pitch = This->bytesPerPixel * This->pow2Width;
dst_pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);
src_pitch = (src_pitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * This->pow2Height);
} else {
mem = This->resource.allocatedMemory;
}
TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
This->glDescription.glFormat, This->glDescription.glType, mem);
ENTER_GL();
glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat,
This->glDescription.glType, This->resource.allocatedMemory);
This->glDescription.glType, mem);
checkGLcall("glGetTexImage()");
LEAVE_GL();
if (wined3d_settings.nonpower2_mode == NP2_REPACK) {
if (This->Flags & SFLAG_NONPOW2) {
LPBYTE src_data, dst_data;
int y;
/*
* Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
* the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
@ -124,23 +139,22 @@ static void surface_download_data(IWineD3DSurfaceImpl *This) {
*
* 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.
*
* Performance should not be an issue, because applications normally do not lock the surfaces when
* rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
* and doesn't have to be re-read.
*/
if (This->Flags & SFLAG_NONPOW2) {
LPBYTE src_data, dst_data;
int src_pitch = This->bytesPerPixel * This->pow2Width;
int dst_pitch = This->bytesPerPixel * This->currentDesc.Width;
int y;
src_data = dst_data = This->resource.allocatedMemory;
FIXME("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
for (y = 1 ; y < This->currentDesc.Height; y++) {
/* skip the first row */
src_data += src_pitch;
dst_data += dst_pitch;
memcpy(dst_data, src_data, dst_pitch);
}
src_data = mem;
dst_data = This->resource.allocatedMemory;
TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
for (y = 1 ; y < This->currentDesc.Height; y++) {
/* skip the first row */
src_data += src_pitch;
dst_data += dst_pitch;
memcpy(dst_data, src_data, dst_pitch);
}
HeapFree(GetProcessHeap(), 0, mem);
}
}
}
@ -1152,18 +1166,9 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
}
b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if( (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
b_info->bmiHeader.biWidth = This->currentDesc.Width;
b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
/* Use the full pow2 image size(assigned below) because LockRect
* will need it for a full glGetTexImage call
*/
} else {
b_info->bmiHeader.biWidth = This->pow2Width;
b_info->bmiHeader.biHeight = -This->pow2Height -extraline;
b_info->bmiHeader.biSizeImage = This->resource.size + extraline * IWineD3DSurface_GetPitch(iface);
}
b_info->bmiHeader.biWidth = This->currentDesc.Width;
b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
b_info->bmiHeader.biPlanes = 1;
b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
@ -1654,11 +1659,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
/* The width is in 'length' not in bytes */
if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET)
width = This->currentDesc.Width;
else
width = This->pow2Width;
width = This->currentDesc.Width;
pitch = IWineD3DSurface_GetPitch(iface);
if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
@ -1688,11 +1689,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
/* Make sure the correct pitch is used */
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
if (NP2_REPACK == wined3d_settings.nonpower2_mode && (This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
TRACE("non power of two support\n");
surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
if (mem) {
surface_upload_data(This, This->pow2Width, This->pow2Height, format, type, mem);
surface_upload_data(This, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
}
} else {
surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
@ -2995,12 +2996,7 @@ DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
ret = ((This->currentDesc.Width + 3) >> 2) << 4;
else {
if (NP2_REPACK == wined3d_settings.nonpower2_mode || This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
/* Front and back buffers are always lockes/unlocked on currentDesc.Width */
ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
} else {
ret = This->bytesPerPixel * This->pow2Width;
}
ret = This->bytesPerPixel * This->currentDesc.Width; /* Bytes / row */
/* Surfaces are 32 bit aligned */
ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
}

View File

@ -40,7 +40,6 @@ wined3d_settings_t wined3d_settings =
PS_HW, /* Hardware by default */
VBO_HW, /* Hardware by default */
FALSE, /* Use of GLSL disabled by default */
NP2_NATIVE, /* Use native NPOT textures, when available */
ORM_BACKBUFFER, /* Use the backbuffer to do offscreen rendering */
RTL_AUTO, /* Automatically determine best locking method */
64*1024*1024 /* 64MB texture memory by default */
@ -188,21 +187,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
TRACE("Use of GL Shading Language disabled\n");
}
}
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 textures\n");
wined3d_settings.nonpower2_mode = NP2_REPACK;
}
/* There will be a couple of other choices for nonpow2, they are: TextureRecrangle and OpenGL 2 */
}
if ( !get_config_key( hkey, appkey, "OffscreenRenderingMode", buffer, size) )
{
if (!strcmp(buffer,"backbuffer"))
@ -271,8 +255,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
TRACE("Disable Vertex Buffer Hardware support\n");
if (wined3d_settings.glslRequested)
TRACE("If supported by your system, GL Shading Language will be used\n");
if (wined3d_settings.nonpower2_mode == NP2_REPACK)
TRACE("Repacking non-power2 textures\n");
if (appkey) RegCloseKey( appkey );
if (hkey) RegCloseKey( hkey );

View File

@ -161,8 +161,6 @@ typedef struct wined3d_settings_s {
we should use it. However, until it's fully implemented, we'll leave it as a registry
setting for developers. */
BOOL glslRequested;
/* nonpower 2 function */
int nonpower2_mode;
int offscreen_rendering_mode;
int rendertargetlock_mode;
/* Memory tracking and object counting */