ddraw: Reserve extra space for video memory surfaces in compatibility mode.
Some old apps write surface data past the end of locked space. That used to work on early ddraw hardware as locked surface provided direct access to video memory mapped to CPU address space and such access could often go without issues. Currently ddraw on Windows allocates bigger buffers for video memory surfaces when 8 or 16 bit display mode is requested. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48788 Signed-off-by: Paul Gofman <gofmanp@gmail.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
dfc159d874
commit
d0ff5e66a7
|
@ -219,6 +219,8 @@ struct ddraw_texture
|
|||
|
||||
struct ddraw_surface *root;
|
||||
struct wined3d_device *wined3d_device;
|
||||
|
||||
void *texture_memory;
|
||||
};
|
||||
|
||||
HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
|
||||
|
|
|
@ -5832,8 +5832,11 @@ static const struct wined3d_parent_ops ddraw_surface_wined3d_parent_ops =
|
|||
|
||||
static void STDMETHODCALLTYPE ddraw_texture_wined3d_object_destroyed(void *parent)
|
||||
{
|
||||
TRACE("parent %p.\n", parent);
|
||||
struct ddraw_texture *texture = parent;
|
||||
|
||||
TRACE("texture %p, texture_memory %p.\n", texture, texture->texture_memory);
|
||||
|
||||
heap_free(texture->texture_memory);
|
||||
heap_free(parent);
|
||||
}
|
||||
|
||||
|
@ -5847,18 +5850,50 @@ static HRESULT CDECL ddraw_reset_enum_callback(struct wined3d_resource *resource
|
|||
return DD_OK;
|
||||
}
|
||||
|
||||
static HRESULT ddraw_surface_reserve_memory(struct wined3d_texture *wined3d_texture)
|
||||
{
|
||||
static const unsigned int extra_size = 0x10000;
|
||||
|
||||
struct ddraw_texture *texture = wined3d_texture_get_parent(wined3d_texture);
|
||||
struct wined3d_resource_desc desc;
|
||||
unsigned int pitch, slice_pitch;
|
||||
HRESULT hr;
|
||||
|
||||
wined3d_resource_get_desc(wined3d_texture_get_resource(wined3d_texture), &desc);
|
||||
if (!(texture->texture_memory = heap_alloc_zero(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)))
|
||||
{
|
||||
heap_free(texture->texture_memory);
|
||||
texture->texture_memory = NULL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_desc,
|
||||
struct ddraw_surface **surface, IUnknown *outer_unknown, unsigned int version)
|
||||
{
|
||||
struct wined3d_sub_resource_desc wined3d_mip_desc;
|
||||
struct ddraw_surface *root, *mip, **attach;
|
||||
struct wined3d_resource_desc wined3d_desc;
|
||||
DDPIXELFORMAT wined3d_display_mode_format;
|
||||
struct wined3d_texture *wined3d_texture;
|
||||
struct wined3d_display_mode mode;
|
||||
DDSURFACEDESC2 *desc, *mip_desc;
|
||||
struct ddraw_texture *texture;
|
||||
unsigned int layers = 1;
|
||||
unsigned int pitch = 0;
|
||||
BOOL reserve_memory;
|
||||
UINT levels, i, j;
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -5879,6 +5914,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
|
|||
if (!(texture = heap_alloc(sizeof(*texture))))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
texture->texture_memory = NULL;
|
||||
texture->version = version;
|
||||
texture->surface_desc = *surface_desc;
|
||||
desc = &texture->surface_desc;
|
||||
|
@ -6020,12 +6056,14 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
|
|||
return hr_ddraw_from_wined3d(hr);
|
||||
}
|
||||
|
||||
wined3d_display_mode_format.dwSize = sizeof(wined3d_display_mode_format);
|
||||
ddrawformat_from_wined3dformat(&wined3d_display_mode_format, mode.format_id);
|
||||
|
||||
/* No pixelformat given? Use the current screen format. */
|
||||
if (!(desc->dwFlags & DDSD_PIXELFORMAT))
|
||||
{
|
||||
desc->dwFlags |= DDSD_PIXELFORMAT;
|
||||
desc->u4.ddpfPixelFormat.dwSize = sizeof(desc->u4.ddpfPixelFormat);
|
||||
ddrawformat_from_wined3dformat(&desc->u4.ddpfPixelFormat, mode.format_id);
|
||||
desc->u4.ddpfPixelFormat = wined3d_display_mode_format;
|
||||
}
|
||||
|
||||
wined3d_desc.resource_type = WINED3D_RTYPE_TEXTURE_2D;
|
||||
|
@ -6434,6 +6472,16 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
|
|||
goto fail;
|
||||
}
|
||||
|
||||
reserve_memory = !(desc->dwFlags & DDSD_LPSURFACE)
|
||||
&& desc->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY
|
||||
&& wined3d_display_mode_format.u1.dwRGBBitCount <= 16;
|
||||
|
||||
if (reserve_memory && FAILED(hr = ddraw_surface_reserve_memory(wined3d_texture)))
|
||||
{
|
||||
ERR("Failed to reserve surface memory, hr %#x.\n", hr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (desc->dwFlags & DDSD_BACKBUFFERCOUNT)
|
||||
{
|
||||
unsigned int count = desc->u5.dwBackBufferCount;
|
||||
|
@ -6448,6 +6496,7 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
|
|||
goto fail;
|
||||
}
|
||||
|
||||
texture->texture_memory = NULL;
|
||||
texture->version = version;
|
||||
texture->surface_desc = root->surface_desc;
|
||||
desc = &texture->surface_desc;
|
||||
|
@ -6487,6 +6536,12 @@ HRESULT ddraw_surface_create(struct ddraw *ddraw, const DDSURFACEDESC2 *surface_
|
|||
wined3d_texture_set_color_key(wined3d_texture, DDCKEY_SRCBLT,
|
||||
(struct wined3d_color_key *)&desc->ddckCKSrcBlt);
|
||||
|
||||
if (reserve_memory && FAILED(hr = ddraw_surface_reserve_memory(wined3d_texture)))
|
||||
{
|
||||
hr = hr_ddraw_from_wined3d(hr);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*attach = last;
|
||||
attach = &last->complex_array[0];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue