[6/10] WineD3D: Always use np2 repacking if no native np2 support is available

Stefan Dösinger stefan at codeweavers.com
Tue Feb 13 13:21:48 CST 2007


Also removes the np2 method setting from wined3d
-------------- next part --------------
From 377d4dc7b2d4d53c79a8511a4fbed4eba1957baf Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Thu, 8 Feb 2007 23:41:59 +0100
Subject: [PATCH] WineD3D: Always use np2 repacking if no native np2 support is available

This way the pitch reported to the application does not depend on the availibility of the np2 extension, we can
remove a configuration setting and make render target handling cleaner. The use of np2 on render targets in any
situation caused some bad issues. It saves memory for textures which have a local copy for any reason.

The opengl texture still has the full power of 2, so the scaling with the texture matrix is still needed, and it
will not fix np2 textures with pixel shaders.

Performance should not be an issue because the local texture copy is not released any more if the texture is
locked regularly, so no readback and repack is needed.
---
 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 06a5716..42ebf2d 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 51caef6..5804df8 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 7bd04bb..d7f8d6d 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 ee5ba98..11b04a8 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 fe957d4..54a5214 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 a3fc80b..719f176 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 9c5cf33..c59764b 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 */
-- 
1.4.4.3



More information about the wine-patches mailing list