[PATCH 4/7] wined3d: Allow texture updates in some cases even when mip levels don't match. (resend)

Matteo Bruni mbruni at codeweavers.com
Tue Mar 17 09:52:12 CDT 2015


It fixes bug 38048.
---
 dlls/wined3d/device.c | 47 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 32 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 8cab927..fc7b978 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3519,7 +3519,7 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
         struct wined3d_texture *src_texture, struct wined3d_texture *dst_texture)
 {
     enum wined3d_resource_type type;
-    unsigned int level_count, i;
+    unsigned int level_count, i, j, src_size, dst_size, src_skip_levels = 0;
     HRESULT hr;
     struct wined3d_context *context;
 
@@ -3551,12 +3551,20 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
         return WINED3DERR_INVALIDCALL;
     }
 
-    /* Check that both textures have the identical numbers of levels. */
-    level_count = wined3d_texture_get_level_count(src_texture);
-    if (wined3d_texture_get_level_count(dst_texture) != level_count)
+    level_count = min(wined3d_texture_get_level_count(src_texture),
+            wined3d_texture_get_level_count(dst_texture));
+
+    src_size = max(src_texture->resource.width, src_texture->resource.height);
+    dst_size = max(dst_texture->resource.width, dst_texture->resource.height);
+    if (type == WINED3D_RTYPE_VOLUME)
     {
-        WARN("Source and destination have different level counts, returning WINED3DERR_INVALIDCALL.\n");
-        return WINED3DERR_INVALIDCALL;
+        src_size = max(src_size, src_texture->resource.depth);
+        dst_size = max(dst_size, dst_texture->resource.depth);
+    }
+    while (src_size > dst_size)
+    {
+        src_size >>= 1;
+        ++src_skip_levels;
     }
 
     /* Make sure that the destination texture is loaded. */
@@ -3574,7 +3582,8 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
 
             for (i = 0; i < level_count; ++i)
             {
-                src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i));
+                src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture,
+                        i + src_skip_levels));
                 dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i));
                 hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL);
                 if (FAILED(hr))
@@ -3590,16 +3599,23 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
         {
             struct wined3d_surface *src_surface;
             struct wined3d_surface *dst_surface;
+            unsigned int src_levels = wined3d_texture_get_level_count(src_texture);
+            unsigned int dst_levels = wined3d_texture_get_level_count(dst_texture);
 
-            for (i = 0; i < level_count * 6; ++i)
+            for (i = 0; i < 6; ++i)
             {
-                src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture, i));
-                dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture, i));
-                hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL);
-                if (FAILED(hr))
+                for (j = 0; j < level_count; ++j)
                 {
-                    WARN("Failed to update surface, hr %#x.\n", hr);
-                    return hr;
+                    src_surface = surface_from_resource(wined3d_texture_get_sub_resource(src_texture,
+                            i * src_levels + j + src_skip_levels));
+                    dst_surface = surface_from_resource(wined3d_texture_get_sub_resource(dst_texture,
+                            i * dst_levels + j));
+                    hr = wined3d_device_update_surface(device, src_surface, NULL, dst_surface, NULL);
+                    if (FAILED(hr))
+                    {
+                        WARN("Failed to update surface, hr %#x.\n", hr);
+                        return hr;
+                    }
                 }
             }
             break;
@@ -3610,7 +3626,8 @@ HRESULT CDECL wined3d_device_update_texture(struct wined3d_device *device,
             for (i = 0; i < level_count; ++i)
             {
                 hr = device_update_volume(device,
-                        volume_from_resource(wined3d_texture_get_sub_resource(src_texture, i)),
+                        volume_from_resource(wined3d_texture_get_sub_resource(src_texture,
+                                i + src_skip_levels)),
                         volume_from_resource(wined3d_texture_get_sub_resource(dst_texture, i)));
                 if (FAILED(hr))
                 {
-- 
2.0.5




More information about the wine-patches mailing list