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.

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 11b5707..354f214 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -716,7 +716,7 @@
                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 @@
 
 
         } 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)
                 );
+            }
 
         }
      }
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index c40b314..b9c0be9 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -284,8 +284,13 @@
     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 @@
                             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 @@
     } 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 @@
                 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 @@
             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,
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c
index e6c7b31..e437aa2 100644
--- a/dlls/wined3d/wined3d_main.c
+++ b/dlls/wined3d/wined3d_main.c
@@ -113,24 +113,24 @@
        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 @@
                     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 @@
            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 );
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4b2c781..84edf86 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -110,21 +110,26 @@
 /**
  * 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;