From b48dfb3c547f060270b96e51f6bebc9ce1d0a891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 13 Feb 2007 20:21:48 +0100 Subject: [PATCH] wined3d: Always use np2 repacking if no native np2 support is available. --- dlls/d3d9/tests/surface.c | 6 +-- dlls/wined3d/device.c | 44 +++++------------- dlls/wined3d/directx.c | 6 --- dlls/wined3d/state.c | 2 +- dlls/wined3d/surface.c | 82 ++++++++++++++++------------------ dlls/wined3d/wined3d_main.c | 18 -------- dlls/wined3d/wined3d_private.h | 2 - 7 files changed, 55 insertions(+), 105 deletions(-) diff --git a/dlls/d3d9/tests/surface.c b/dlls/d3d9/tests/surface.c index 06a57161e9b..42ebf2d0fb7 100644 --- a/dlls/d3d9/tests/surface.c +++ b/dlls/d3d9/tests/surface.c @@ -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); } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 51caef6ca56..5804df8e43a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -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 { diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 7bd04bb4e0f..d7f8d6d0535 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -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"); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 61ab2156541..ef1d3a6e5a2 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -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 ) { diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index fe957d40b1f..54a5214cc8d 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -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); } diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index a3fc80b94f1..719f176a63d 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -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 ); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9c5cf339b0d..c59764b708f 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -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 */