Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49375 Signed-off-by: Paul Gofman pgofman@codeweavers.com --- Supersedes 186963-186967.
dlls/wined3d/surface.c | 3 +- dlls/wined3d/texture.c | 72 ++++++++++++---------------------- dlls/wined3d/utils.c | 1 - dlls/wined3d/wined3d_private.h | 1 - 4 files changed, 25 insertions(+), 52 deletions(-)
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 652f6070b93..af2ab36d273 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -33,8 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
-static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM - | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER; +static const DWORD surface_simple_locations = WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_BUFFER;
/* Works correctly only for <= 4 bpp formats. */ static void get_color_masks(const struct wined3d_format *format, DWORD *masks) diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 84020f17c95..b1e08383f62 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -30,8 +30,7 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
#define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
-static const uint32_t wined3d_texture_sysmem_locations = WINED3D_LOCATION_SYSMEM - | WINED3D_LOCATION_USER_MEMORY | WINED3D_LOCATION_BUFFER; +static const uint32_t wined3d_texture_sysmem_locations = WINED3D_LOCATION_SYSMEM | WINED3D_LOCATION_BUFFER; static const struct wined3d_texture_ops texture_gl_ops;
struct wined3d_texture_idx @@ -132,7 +131,6 @@ static DWORD wined3d_resource_access_from_location(DWORD location) return 0;
case WINED3D_LOCATION_SYSMEM: - case WINED3D_LOCATION_USER_MEMORY: return WINED3D_RESOURCE_ACCESS_CPU;
case WINED3D_LOCATION_BUFFER: @@ -733,16 +731,18 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su data->buffer_object = (uintptr_t)&sub_resource->bo; return; } - if (locations & WINED3D_LOCATION_USER_MEMORY) - { - data->addr = texture->user_memory; - data->buffer_object = 0; - return; - } + if (locations & WINED3D_LOCATION_SYSMEM) { - data->addr = texture->resource.heap_memory; - data->addr += sub_resource->offset; + if (texture->user_memory) + { + data->addr = texture->user_memory; + } + else + { + data->addr = texture->resource.heap_memory; + data->addr += sub_resource->offset; + } data->buffer_object = 0; return; } @@ -1741,7 +1741,6 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT unsigned int resource_size; const struct wined3d *d3d; unsigned int slice_pitch; - DWORD valid_location = 0; bool update_memory_only; bool create_dib = false;
@@ -1872,16 +1871,10 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT } }
- if ((texture->user_memory = mem)) - { - texture->resource.map_binding = WINED3D_LOCATION_USER_MEMORY; - valid_location = WINED3D_LOCATION_USER_MEMORY; - } - else + if (!(texture->user_memory = mem)) { if (!wined3d_resource_prepare_sysmem(&texture->resource)) ERR("Failed to allocate resource memory.\n"); - valid_location = WINED3D_LOCATION_SYSMEM; }
/* The format might be changed to a format that needs conversion. @@ -1891,8 +1884,8 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info)) texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
- wined3d_texture_validate_location(texture, 0, valid_location); - wined3d_texture_invalidate_location(texture, 0, ~valid_location); + wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_SYSMEM); + wined3d_texture_invalidate_location(texture, 0, ~WINED3D_LOCATION_SYSMEM);
if (create_dib) { @@ -3123,12 +3116,8 @@ static BOOL wined3d_texture_gl_prepare_location(struct wined3d_texture *texture, switch (location) { case WINED3D_LOCATION_SYSMEM: - return wined3d_resource_prepare_sysmem(&texture->resource); - - case WINED3D_LOCATION_USER_MEMORY: - if (!texture->user_memory) - ERR("Preparing WINED3D_LOCATION_USER_MEMORY, but texture->user_memory is NULL.\n"); - return TRUE; + return texture->user_memory ? TRUE + : wined3d_resource_prepare_sysmem(&texture->resource);
case WINED3D_LOCATION_BUFFER: wined3d_texture_prepare_buffer_object(texture, sub_resource_idx, context_gl->gl_info); @@ -3176,7 +3165,6 @@ static BOOL wined3d_texture_gl_load_location(struct wined3d_texture *texture,
switch (location) { - case WINED3D_LOCATION_USER_MEMORY: case WINED3D_LOCATION_SYSMEM: case WINED3D_LOCATION_BUFFER: return wined3d_texture_gl_load_sysmem(texture_gl, sub_resource_idx, context_gl, location); @@ -4431,20 +4419,12 @@ static void wined3d_texture_no3d_download_data(struct wined3d_context *context, static BOOL wined3d_texture_no3d_prepare_location(struct wined3d_texture *texture, unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { - switch (location) - { - case WINED3D_LOCATION_SYSMEM: - return wined3d_resource_prepare_sysmem(&texture->resource); - - case WINED3D_LOCATION_USER_MEMORY: - if (!texture->user_memory) - ERR("Preparing WINED3D_LOCATION_USER_MEMORY, but texture->user_memory is NULL.\n"); - return TRUE; + if (location == WINED3D_LOCATION_SYSMEM) + return texture->user_memory ? TRUE + : wined3d_resource_prepare_sysmem(&texture->resource);
- default: - FIXME("Unhandled location %s.\n", wined3d_debug_location(location)); - return FALSE; - } + FIXME("Unhandled location %s.\n", wined3d_debug_location(location)); + return FALSE; }
static BOOL wined3d_texture_no3d_load_location(struct wined3d_texture *texture, @@ -4453,7 +4433,7 @@ static BOOL wined3d_texture_no3d_load_location(struct wined3d_texture *texture, TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n", texture, sub_resource_idx, context, wined3d_debug_location(location));
- if (location == WINED3D_LOCATION_USER_MEMORY || location == WINED3D_LOCATION_SYSMEM) + if (location == WINED3D_LOCATION_SYSMEM) return TRUE;
ERR("Unhandled location %s.\n", wined3d_debug_location(location)); @@ -5078,12 +5058,8 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, switch (location) { case WINED3D_LOCATION_SYSMEM: - return wined3d_resource_prepare_sysmem(&texture->resource); - - case WINED3D_LOCATION_USER_MEMORY: - if (!texture->user_memory) - ERR("Preparing WINED3D_LOCATION_USER_MEMORY, but texture->user_memory is NULL.\n"); - return TRUE; + return texture->user_memory ? TRUE + : wined3d_resource_prepare_sysmem(&texture->resource);
case WINED3D_LOCATION_TEXTURE_RGB: return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture), wined3d_context_vk(context)); diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index d078c503df3..2a3c04f4352 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -6643,7 +6643,6 @@ const char *wined3d_debug_location(DWORD location) #define LOCATION_TO_STR(x) if (location & x) { debug_append(&buffer, #x, " | "); location &= ~x; } LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED); LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM); - LOCATION_TO_STR(WINED3D_LOCATION_USER_MEMORY); LOCATION_TO_STR(WINED3D_LOCATION_BUFFER); LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_RGB); LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_SRGB); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 17acd4be4d5..9556f8c0abb 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3988,7 +3988,6 @@ void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DEC
#define WINED3D_LOCATION_DISCARDED 0x00000001 #define WINED3D_LOCATION_SYSMEM 0x00000002 -#define WINED3D_LOCATION_USER_MEMORY 0x00000004 #define WINED3D_LOCATION_BUFFER 0x00000008 #define WINED3D_LOCATION_TEXTURE_RGB 0x00000010 #define WINED3D_LOCATION_TEXTURE_SRGB 0x00000020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43232 Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/d3d9/device.c | 4 +- dlls/ddraw/surface.c | 80 +++++++++++++++++++--------------- dlls/wined3d/swapchain.c | 4 +- dlls/wined3d/texture.c | 78 +++++++++++++++++++++------------ dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 3 +- include/wine/wined3d.h | 2 +- 7 files changed, 105 insertions(+), 68 deletions(-)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 2ee582b4c54..9b1dac0b58c 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -1339,7 +1339,7 @@ static HRESULT WINAPI d3d9_device_CreateTexture(IDirect3DDevice9Ex *iface, }
if (set_mem) - wined3d_texture_update_desc(object->wined3d_texture, width, height, + wined3d_texture_update_desc(object->wined3d_texture, 0, width, height, wined3dformat_from_d3dformat(format), WINED3D_MULTISAMPLE_NONE, 0, *shared_handle, 0);
@@ -1577,7 +1577,7 @@ static HRESULT d3d9_device_create_surface(struct d3d9_device *device, unsigned i IDirect3DSurface9_AddRef(*surface);
if (user_mem) - wined3d_texture_update_desc(texture, width, height, desc.format, + wined3d_texture_update_desc(texture, 0, width, height, desc.format, multisample_type, multisample_quality, user_mem, 0);
wined3d_texture_decref(texture); diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index b229f1a7156..b6bd5535abf 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -4614,7 +4614,7 @@ static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDire *****************************************************************************/ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags) { - struct ddraw_surface *This = impl_from_IDirectDrawSurface7(iface); + struct ddraw_surface *surface = impl_from_IDirectDrawSurface7(iface); HRESULT hr; const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS; @@ -4633,9 +4633,9 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, WARN("Flags is %x, returning DDERR_INVALIDPARAMS\n", Flags); return DDERR_INVALIDPARAMS; } - if (!(This->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) - || This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE - || This->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) + if (!(surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) + || surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE + || surface->surface_desc.ddsCaps.dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) { WARN("Surface is not in system memory, returning DDERR_INVALIDSURFACETYPE.\n"); return DDERR_INVALIDSURFACETYPE; @@ -4671,10 +4671,10 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSD->u1.lPitch, DDSD->dwWidth); return DDERR_INVALIDPARAMS; } - if (DDSD->dwWidth != This->surface_desc.dwWidth) - TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth); - if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch) - TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch); + if (DDSD->dwWidth != surface->surface_desc.dwWidth) + TRACE("Surface width changed from %u to %u.\n", surface->surface_desc.dwWidth, DDSD->dwWidth); + if (DDSD->u1.lPitch != surface->surface_desc.u1.lPitch) + TRACE("Surface pitch changed from %u to %u.\n", surface->surface_desc.u1.lPitch, DDSD->u1.lPitch); pitch = DDSD->u1.lPitch; width = DDSD->dwWidth; } @@ -4685,8 +4685,8 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, } else { - pitch = This->surface_desc.u1.lPitch; - width = This->surface_desc.dwWidth; + pitch = surface->surface_desc.u1.lPitch; + width = surface->surface_desc.dwWidth; }
if (DDSD->dwFlags & DDSD_HEIGHT) @@ -4696,13 +4696,13 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, WARN("Height is 0, returning DDERR_INVALIDPARAMS.\n"); return DDERR_INVALIDPARAMS; } - if (DDSD->dwHeight != This->surface_desc.dwHeight) - TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight); + if (DDSD->dwHeight != surface->surface_desc.dwHeight) + TRACE("Surface height changed from %u to %u.\n", surface->surface_desc.dwHeight, DDSD->dwHeight); height = DDSD->dwHeight; } else { - height = This->surface_desc.dwHeight; + height = surface->surface_desc.dwHeight; }
wined3d_mutex_lock(); @@ -4717,17 +4717,17 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, wined3d_mutex_unlock(); return DDERR_INVALIDPARAMS; } - current_format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); + current_format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat); if (format_id != current_format_id) TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id); } else { - format_id = wined3dformat_from_ddrawformat(&This->surface_desc.u4.ddpfPixelFormat); + format_id = wined3dformat_from_ddrawformat(&surface->surface_desc.u4.ddpfPixelFormat); }
- if (FAILED(hr = wined3d_texture_update_desc(This->wined3d_texture, width, height, - format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch))) + if (FAILED(hr = wined3d_texture_update_desc(surface->wined3d_texture, surface->sub_resource_idx, + width, height, format_id, WINED3D_MULTISAMPLE_NONE, 0, DDSD->lpSurface, pitch))) { WARN("Failed to update surface desc, hr %#x.\n", hr); wined3d_mutex_unlock(); @@ -4735,13 +4735,13 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, }
if (DDSD->dwFlags & DDSD_WIDTH) - This->surface_desc.dwWidth = width; + surface->surface_desc.dwWidth = width; if (DDSD->dwFlags & DDSD_PITCH) - This->surface_desc.u1.lPitch = DDSD->u1.lPitch; + surface->surface_desc.u1.lPitch = DDSD->u1.lPitch; if (DDSD->dwFlags & DDSD_HEIGHT) - This->surface_desc.dwHeight = height; + surface->surface_desc.dwHeight = height; if (DDSD->dwFlags & DDSD_PIXELFORMAT) - This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat; + surface->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
wined3d_mutex_unlock();
@@ -5863,28 +5863,40 @@ static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_text static const unsigned int extra_size = 0x10000;
struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture); - struct wined3d_resource_desc desc; + struct wined3d_resource_desc resource_desc; + struct wined3d_sub_resource_desc desc; unsigned int pitch, slice_pitch; - HRESULT hr; + unsigned int sub_resource_idx; + HRESULT hr = WINED3D_OK; + unsigned int offset;
- wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &desc); - if (!(texture->texture_memory = heap_alloc_zero(desc.size + extra_size))) + wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &resource_desc); + if (!(texture->texture_memory = heap_alloc_zero(resource_desc.size + extra_size))) { ERR("Out of memory.\n"); return E_OUTOFMEMORY; } TRACE("texture->texture_memory %p.\n", texture->texture_memory);
- wined3d_texture_get_pitch(wined3d_texture, 0, &pitch, &slice_pitch); - - if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture, - desc.width, desc.height, desc.format, - WINED3D_MULTISAMPLE_NONE, 0, texture->texture_memory, pitch))) + offset = 0; + sub_resource_idx = 0; + while (wined3d_texture_get_sub_resource_desc(wined3d_texture, sub_resource_idx, &desc) + == WINED3D_OK) { - heap_free(texture->texture_memory); - texture->texture_memory = NULL; - } + wined3d_texture_get_pitch(wined3d_texture, sub_resource_idx, &pitch, &slice_pitch);
+ if (FAILED(hr = wined3d_texture_update_desc(wined3d_texture, sub_resource_idx, + desc.width, desc.height, resource_desc.format, + desc.multisample_type, desc.multisample_quality, + (BYTE *)texture->texture_memory + offset, pitch))) + { + heap_free(texture->texture_memory); + texture->texture_memory = NULL; + break; + } + ++sub_resource_idx; + offset += desc.size; + } return hr; }
@@ -6481,7 +6493,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_ } }
- if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, + if ((desc->dwFlags & DDSD_LPSURFACE) && FAILED(hr = wined3d_texture_update_desc(wined3d_texture, 0, wined3d_desc.width, wined3d_desc.height, wined3d_desc.format, WINED3D_MULTISAMPLE_NONE, 0, desc->lpSurface, pitch))) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index e034bdf6241..e9d62728b48 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -1925,14 +1925,14 @@ HRESULT CDECL wined3d_swapchain_resize_buffers(struct wined3d_swapchain *swapcha HRESULT hr; UINT i;
- if (FAILED(hr = wined3d_texture_update_desc(swapchain->front_buffer, desc->backbuffer_width, + if (FAILED(hr = wined3d_texture_update_desc(swapchain->front_buffer, 0, desc->backbuffer_width, desc->backbuffer_height, desc->backbuffer_format, desc->multisample_type, desc->multisample_quality, NULL, 0))) return hr;
for (i = 0; i < desc->backbuffer_count; ++i) { - if (FAILED(hr = wined3d_texture_update_desc(swapchain->back_buffers[i], desc->backbuffer_width, + if (FAILED(hr = wined3d_texture_update_desc(swapchain->back_buffers[i], 0, desc->backbuffer_width, desc->backbuffer_height, desc->backbuffer_format, desc->multisample_type, desc->multisample_quality, NULL, 0))) return hr; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index b1e08383f62..4070062d244 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -734,9 +734,9 @@ void wined3d_texture_get_memory(struct wined3d_texture *texture, unsigned int su
if (locations & WINED3D_LOCATION_SYSMEM) { - if (texture->user_memory) + if (texture->sub_resources[sub_resource_idx].user_memory) { - data->addr = texture->user_memory; + data->addr = texture->sub_resources[sub_resource_idx].user_memory; } else { @@ -1416,6 +1416,7 @@ static void wined3d_texture_cleanup_sync(struct wined3d_texture *texture)
ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture) { + unsigned int i, sub_resource_count; ULONG refcount;
TRACE("texture %p, swapchain %p.\n", texture, texture->swapchain); @@ -1432,8 +1433,15 @@ ULONG CDECL wined3d_texture_decref(struct wined3d_texture *texture) * since the application is allowed to free that memory once the * texture is destroyed. Note that this implies that * the destroy handler can't access that memory either. */ - if (texture->user_memory) - wined3d_resource_wait_idle(&texture->resource); + sub_resource_count = texture->layer_count * texture->level_count; + for (i = 0; i < sub_resource_count; ++i) + { + if (texture->sub_resources[i].user_memory) + { + wined3d_resource_wait_idle(&texture->resource); + break; + } + } texture->resource.device->adapter->adapter_ops->adapter_destroy_texture(texture); }
@@ -1729,11 +1737,12 @@ void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl *t checkGLcall("set compatible renderbuffer"); }
-HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT width, UINT height, - enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, - UINT multisample_quality, void *mem, UINT pitch) +HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, unsigned int sub_resource_idx, + UINT width, UINT height, enum wined3d_format_id format_id, + enum wined3d_multisample_type multisample_type, UINT multisample_quality, void *mem, UINT pitch) { struct wined3d_texture_sub_resource *sub_resource; + unsigned int i, level, sub_resource_count; const struct wined3d_d3d_info *d3d_info; const struct wined3d_gl_info *gl_info; const struct wined3d_format *format; @@ -1745,8 +1754,9 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT bool create_dib = false;
TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, " - "mem %p, pitch %u.\n", - texture, width, height, debug_d3dformat(format_id), multisample_type, multisample_quality, mem, pitch); + "mem %p, pitch %u, sub_resource_idx %u.\n", + texture, width, height, debug_d3dformat(format_id), multisample_type, multisample_quality, mem, pitch, + sub_resource_idx);
device = texture->resource.device; d3d = device->wined3d; @@ -1754,8 +1764,11 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT d3d_info = &device->adapter->d3d_info; format = wined3d_get_format(device->adapter, format_id, texture->resource.bind_flags); resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height, 1); + level = sub_resource_idx % texture->level_count; + sub_resource_count = texture->level_count * texture->layer_count;
- update_memory_only = width == texture->resource.width && height == texture->resource.height + update_memory_only = width == wined3d_texture_get_level_width(texture, level) + && height == wined3d_texture_get_level_height(texture, level) && format_id == texture->resource.format->id && multisample_type == texture->resource.multisample_type && multisample_quality == texture->resource.multisample_quality;
@@ -1768,16 +1781,16 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT { unsigned int current_row_pitch, current_slice_pitch;
- wined3d_texture_get_pitch(texture, 0, ¤t_row_pitch, ¤t_slice_pitch); + wined3d_texture_get_pitch(texture, level, ¤t_row_pitch, ¤t_slice_pitch); update_memory_only = pitch == current_row_pitch && slice_pitch == current_slice_pitch; }
if (!resource_size) return WINED3DERR_INVALIDCALL;
- if (texture->level_count * texture->layer_count > 1 && !update_memory_only) + if (sub_resource_count > 1 && !update_memory_only) { - WARN("Texture has multiple sub-resources, not supported.\n"); + FIXME("Texture has multiple sub-resources, not supported.\n"); return WINED3DERR_INVALIDCALL; }
@@ -1812,18 +1825,32 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT
if (texture->dc_info && texture->dc_info[0].dc) { - struct wined3d_texture_idx texture_idx = {texture, 0}; + struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
wined3d_cs_destroy_object(device->cs, wined3d_texture_destroy_dc, &texture_idx); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); create_dib = true; }
- wined3d_resource_free_sysmem(&texture->resource); + texture->sub_resources[sub_resource_idx].user_memory = mem; + + if (update_memory_only) + { + for (i = 0; i < sub_resource_count; ++i) + if (!texture->sub_resources[i].user_memory) + break; + + if (i == sub_resource_count) + wined3d_resource_free_sysmem(&texture->resource); + } + else + { + wined3d_resource_free_sysmem(&texture->resource); + }
if (!update_memory_only) { - sub_resource = &texture->sub_resources[0]; + sub_resource = &texture->sub_resources[sub_resource_idx];
texture->row_pitch = pitch; texture->slice_pitch = slice_pitch; @@ -1871,11 +1898,8 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT } }
- if (!(texture->user_memory = mem)) - { - if (!wined3d_resource_prepare_sysmem(&texture->resource)) - ERR("Failed to allocate resource memory.\n"); - } + if (!mem && !wined3d_resource_prepare_sysmem(&texture->resource)) + ERR("Failed to allocate resource memory.\n");
/* The format might be changed to a format that needs conversion. * If the surface didn't use PBOs previously but could now, don't @@ -1884,12 +1908,12 @@ HRESULT CDECL wined3d_texture_update_desc(struct wined3d_texture *texture, UINT if (texture->resource.map_binding == WINED3D_LOCATION_BUFFER && !wined3d_texture_use_pbo(texture, gl_info)) texture->resource.map_binding = WINED3D_LOCATION_SYSMEM;
- wined3d_texture_validate_location(texture, 0, WINED3D_LOCATION_SYSMEM); - wined3d_texture_invalidate_location(texture, 0, ~WINED3D_LOCATION_SYSMEM); + wined3d_texture_validate_location(texture, sub_resource_idx, WINED3D_LOCATION_SYSMEM); + wined3d_texture_invalidate_location(texture, sub_resource_idx, ~WINED3D_LOCATION_SYSMEM);
if (create_dib) { - struct wined3d_texture_idx texture_idx = {texture, 0}; + struct wined3d_texture_idx texture_idx = {texture, sub_resource_idx};
wined3d_cs_init_object(device->cs, wined3d_texture_create_dc, &texture_idx); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); @@ -3116,7 +3140,7 @@ static BOOL wined3d_texture_gl_prepare_location(struct wined3d_texture *texture, switch (location) { case WINED3D_LOCATION_SYSMEM: - return texture->user_memory ? TRUE + return texture->sub_resources[sub_resource_idx].user_memory ? TRUE : wined3d_resource_prepare_sysmem(&texture->resource);
case WINED3D_LOCATION_BUFFER: @@ -4420,7 +4444,7 @@ static BOOL wined3d_texture_no3d_prepare_location(struct wined3d_texture *textur unsigned int sub_resource_idx, struct wined3d_context *context, unsigned int location) { if (location == WINED3D_LOCATION_SYSMEM) - return texture->user_memory ? TRUE + return texture->sub_resources[sub_resource_idx].user_memory ? TRUE : wined3d_resource_prepare_sysmem(&texture->resource);
FIXME("Unhandled location %s.\n", wined3d_debug_location(location)); @@ -5058,7 +5082,7 @@ static BOOL wined3d_texture_vk_prepare_location(struct wined3d_texture *texture, switch (location) { case WINED3D_LOCATION_SYSMEM: - return texture->user_memory ? TRUE + return texture->sub_resources[sub_resource_idx].user_memory ? TRUE : wined3d_resource_prepare_sysmem(&texture->resource);
case WINED3D_LOCATION_TEXTURE_RGB: diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index f4a648cac8b..295b50a32c7 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -307,7 +307,7 @@ @ cdecl wined3d_texture_set_lod(ptr long) @ cdecl wined3d_texture_set_overlay_position(ptr long long long) @ cdecl wined3d_texture_set_sub_resource_parent(ptr long ptr) -@ cdecl wined3d_texture_update_desc(ptr long long long long long ptr long) +@ cdecl wined3d_texture_update_desc(ptr long long long long long long ptr long) @ cdecl wined3d_texture_update_overlay(ptr long ptr ptr long ptr long)
@ cdecl wined3d_unordered_access_view_create(ptr ptr ptr ptr ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9556f8c0abb..211d76c97f5 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4059,7 +4059,6 @@ struct wined3d_texture DWORD flags; DWORD update_map_binding;
- void *user_memory; unsigned int row_pitch; unsigned int slice_pitch;
@@ -4112,6 +4111,8 @@ struct wined3d_texture uint32_t map_flags; DWORD locations; struct wined3d_bo_gl bo; + + void *user_memory; } *sub_resources; };
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 5450b4d2117..346d1d0dfa8 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2808,7 +2808,7 @@ HRESULT __cdecl wined3d_texture_set_overlay_position(struct wined3d_texture *tex unsigned int sub_resource_idx, LONG x, LONG y); void __cdecl wined3d_texture_set_sub_resource_parent(struct wined3d_texture *texture, unsigned int sub_resource_idx, void *parent); -HRESULT __cdecl wined3d_texture_update_desc(struct wined3d_texture *texture, +HRESULT __cdecl wined3d_texture_update_desc(struct wined3d_texture *texture, unsigned int sub_resource_idx, UINT width, UINT height, enum wined3d_format_id format_id, enum wined3d_multisample_type multisample_type, UINT multisample_quality, void *mem, UINT pitch);
On Tue, 16 Jun 2020 at 18:09, Paul Gofman pgofman@codeweavers.com wrote:
if (update_memory_only)
{
for (i = 0; i < sub_resource_count; ++i)
if (!texture->sub_resources[i].user_memory)
break;
if (i == sub_resource_count)
wined3d_resource_free_sysmem(&texture->resource);
}
else
{
wined3d_resource_free_sysmem(&texture->resource);
}
if (!update_memory_only) {
sub_resource = &texture->sub_resources[0];
sub_resource = &texture->sub_resources[sub_resource_idx];
It's fairly minor, but these blocks could be merged, right? On the other hand, it also seems tempting to simplify the code by simply always using the "update_memory_only" path here.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ddraw/tests/ddraw7.c | 87 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index c85f0201118..15f552f88e5 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -7147,6 +7147,93 @@ static void test_set_surface_desc(void) * parameters. */ hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_LPSURFACE; + ddsd.lpSurface = data; + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DDERR_INVALIDSURFACETYPE, "Got unexpected hr %#x.\n", hr); + IDirectDrawSurface7_Release(surface); + } + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_MIPMAPCOUNT; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + U2(ddsd).dwMipMapCount = 3; + ddsd.lpSurface = data; + ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP; + + hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &surface, NULL); + ok(hr == DD_OK || hr == DDERR_NODIRECTDRAWHW || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr); + + if (hr == DD_OK) + { + static DDSCAPS2 caps = {DDSCAPS_TEXTURE, 0, 0, {0}}; + void *surface2_system_mem; + IDirectDrawSurface7 *surface2; + + hr = IDirectDrawSurface7_GetAttachedSurface(surface, &caps, &surface2); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + reset_ddsd(&ddsd); + hr = IDirectDrawSurface7_GetSurfaceDesc(surface2, &ddsd); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + ok(ddsd.dwWidth == 4, "Got unexpected dwWidth %u.\n", ddsd.dwWidth); + + hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + surface2_system_mem = ddsd.lpSurface; + IDirectDrawSurface7_Unlock(surface2, NULL); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE; + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + U1(ddsd).lPitch = 16 * 4; + ddsd.lpSurface = data; + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE; + ddsd.dwWidth = 8; + ddsd.dwHeight = 8; + U1(ddsd).lPitch = 8 * 4; + ddsd.lpSurface = data; + hr = IDirectDrawSurface7_SetSurfaceDesc(surface, &ddsd, 0); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + ok(ddsd.lpSurface == surface2_system_mem, "Got unexpected lpSurface %p.\n", ddsd.lpSurface); + IDirectDrawSurface7_Unlock(surface2, NULL); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE; + ddsd.dwWidth = 4; + ddsd.dwHeight = 4; + U1(ddsd).lPitch = 4 * 4; + ddsd.lpSurface = data; + hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + reset_ddsd(&ddsd); + hr = IDirectDrawSurface7_Lock(surface2, NULL, &ddsd, 0, NULL); + ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + ok(ddsd.lpSurface == data, "Got unexpected lpSurface %p.\n", ddsd.lpSurface); + IDirectDrawSurface7_Unlock(surface2, NULL); + + reset_ddsd(&ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE; + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + U1(ddsd).lPitch = 16 * 4; + ddsd.lpSurface = data; + hr = IDirectDrawSurface7_SetSurfaceDesc(surface2, &ddsd, 0); + todo_wine ok(hr == DD_OK, "Got unexpected hr %#x.\n", hr); + + IDirectDrawSurface7_Release(surface2); IDirectDrawSurface7_Release(surface); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=73540
Your paranoid android.
=== debiant (64 bit WoW report) ===
ddraw: ddraw4.c:17476: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1024,739). ddraw4.c:17483: Test failed: Expect window rect (0,0)-(1024,768), got (0,0)-(1024,739).
On Tue, 16 Jun 2020 at 18:09, Paul Gofman pgofman@codeweavers.com wrote:
Signed-off-by: Paul Gofman pgofman@codeweavers.com
dlls/ddraw/tests/ddraw7.c | 87 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
I may have missed this in some previous patches, but test_set_surface_desc() has equivalents for other ddraw versions.