From: Matteo Bruni Subject: [PATCH 4/7] wined3d: Allow texture updates in some cases even when mip levels don't match. (resend) Message-Id: <1426603935-11480-4-git-send-email-mbruni@codeweavers.com> Date: Tue, 17 Mar 2015 15:52:12 +0100 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