ddraw: Implement width and height changes in ddraw_surface7_SetSurfaceDesc().

This commit is contained in:
Henri Verbeet 2012-01-12 21:43:08 +01:00 committed by Alexandre Julliard
parent 881299c6a8
commit afb64506ba
6 changed files with 133 additions and 84 deletions

View File

@ -4122,10 +4122,12 @@ static HRESULT WINAPI ddraw_surface1_SetClipper(IDirectDrawSurface *iface, IDire
static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags) static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, DDSURFACEDESC2 *DDSD, DWORD Flags)
{ {
IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface); IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface);
enum wined3d_format_id newFormat = WINED3DFMT_UNKNOWN;
HRESULT hr; HRESULT hr;
const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH
| DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS; | DDSD_HEIGHT | DDSD_PITCH | DDSD_CAPS;
enum wined3d_format_id format_id;
BOOL update_wined3d = FALSE;
UINT width, height;
TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags); TRACE("iface %p, surface_desc %p, flags %#x.\n", iface, DDSD, Flags);
@ -4177,18 +4179,26 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
} }
if (DDSD->dwWidth != This->surface_desc.dwWidth) if (DDSD->dwWidth != This->surface_desc.dwWidth)
{ {
FIXME("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth); TRACE("Surface width changed from %u to %u.\n", This->surface_desc.dwWidth, DDSD->dwWidth);
update_wined3d = TRUE;
} }
if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch) if (DDSD->u1.lPitch != This->surface_desc.u1.lPitch)
{ {
FIXME("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch); TRACE("Surface pitch changed from %u to %u.\n", This->surface_desc.u1.lPitch, DDSD->u1.lPitch);
update_wined3d = TRUE;
} }
width = DDSD->dwWidth;
} }
else if (DDSD->dwFlags & DDSD_PITCH) else if (DDSD->dwFlags & DDSD_PITCH)
{ {
WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n"); WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n");
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
else
{
width = This->surface_desc.dwWidth;
}
if (DDSD->dwFlags & DDSD_HEIGHT) if (DDSD->dwFlags & DDSD_HEIGHT)
{ {
if (!DDSD->dwHeight) if (!DDSD->dwHeight)
@ -4198,32 +4208,60 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface,
} }
if (DDSD->dwHeight != This->surface_desc.dwHeight) if (DDSD->dwHeight != This->surface_desc.dwHeight)
{ {
FIXME("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight); TRACE("Surface height changed from %u to %u.\n", This->surface_desc.dwHeight, DDSD->dwHeight);
update_wined3d = TRUE;
} }
height = DDSD->dwHeight;
}
else
{
height = This->surface_desc.dwHeight;
} }
wined3d_mutex_lock(); wined3d_mutex_lock();
if (DDSD->dwFlags & DDSD_PIXELFORMAT) if (DDSD->dwFlags & DDSD_PIXELFORMAT)
{ {
newFormat = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat); enum wined3d_format_id current_format_id;
format_id = PixelFormat_DD2WineD3D(&DDSD->u4.ddpfPixelFormat);
if(newFormat == WINED3DFMT_UNKNOWN) if (format_id == WINED3DFMT_UNKNOWN)
{ {
ERR("Requested to set an unknown pixelformat\n"); ERR("Requested to set an unknown pixelformat\n");
wined3d_mutex_unlock(); wined3d_mutex_unlock();
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
if(newFormat != PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat) ) current_format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
if (format_id != current_format_id)
{ {
hr = wined3d_surface_set_format(This->wined3d_surface, newFormat); TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id);
if (FAILED(hr)) update_wined3d = TRUE;
{
wined3d_mutex_unlock();
return hr;
}
This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
} }
} }
else
{
format_id = PixelFormat_DD2WineD3D(&This->surface_desc.u4.ddpfPixelFormat);
}
if (update_wined3d)
{
if (FAILED(hr = wined3d_surface_update_desc(This->wined3d_surface, width, height,
format_id, WINED3D_MULTISAMPLE_NONE, 0)))
{
WARN("Failed to update surface desc, hr %#x.\n", hr);
wined3d_mutex_unlock();
return hr;
}
if (DDSD->dwFlags & DDSD_WIDTH)
This->surface_desc.dwWidth = width;
if (DDSD->dwFlags & DDSD_PITCH)
This->surface_desc.u1.lPitch = DDSD->u1.lPitch;
if (DDSD->dwFlags & DDSD_HEIGHT)
This->surface_desc.dwHeight = height;
if (DDSD->dwFlags & DDSD_PIXELFORMAT)
This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat;
}
if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface) if (DDSD->dwFlags & DDSD_LPSURFACE && DDSD->lpSurface)
{ {
hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface); hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface);

View File

@ -4580,7 +4580,7 @@ static void set_surface_desc_test(void)
hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd); hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr); ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth); ok(ddsd.dwWidth == 8, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
todo_wine ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight); ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
/* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */ /* Pitch and width can be set, but only together, and only with LPSURFACE. They must not be 0 */
reset_ddsd(&ddsd); reset_ddsd(&ddsd);
@ -4612,9 +4612,9 @@ static void set_surface_desc_test(void)
reset_ddsd(&ddsd); reset_ddsd(&ddsd);
hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd); hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd);
ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr); ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr);
todo_wine ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth); ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth);
todo_wine ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight); ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight);
todo_wine ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch); ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch);
/* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise /* The pitch must be 32 bit aligned and > 0, but is not verified for sanity otherwise
* *

View File

@ -5200,69 +5200,6 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device)
device_invalidate_state(device, STATE_STREAMSRC); device_invalidate_state(device, STATE_STREAMSRC);
} }
static HRESULT updateSurfaceDesc(struct wined3d_surface *surface,
const struct wined3d_swapchain_desc *swapchain_desc)
{
struct wined3d_device *device = surface->resource.device;
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
/* Reallocate proper memory for the front and back buffer and adjust their sizes */
if (surface->flags & SFLAG_DIBSECTION)
{
DeleteDC(surface->hDC);
DeleteObject(surface->dib.DIBsection);
surface->dib.bitmap_data = NULL;
surface->resource.allocatedMemory = NULL;
surface->flags &= ~SFLAG_DIBSECTION;
}
surface->resource.width = swapchain_desc->backbuffer_width;
surface->resource.height = swapchain_desc->backbuffer_height;
if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
|| gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
{
surface->pow2Width = swapchain_desc->backbuffer_width;
surface->pow2Height = swapchain_desc->backbuffer_height;
}
else
{
surface->pow2Width = surface->pow2Height = 1;
while (surface->pow2Width < swapchain_desc->backbuffer_width)
surface->pow2Width <<= 1;
while (surface->pow2Height < swapchain_desc->backbuffer_height)
surface->pow2Height <<= 1;
}
if (!(surface->resource.usage & WINED3DUSAGE_DEPTHSTENCIL))
surface->resource.format = wined3d_get_format(gl_info, swapchain_desc->backbuffer_format);
surface->resource.multisample_type = swapchain_desc->multisample_type;
surface->resource.multisample_quality = swapchain_desc->multisample_quality;
if (device->d3d_initialized)
surface->resource.resource_ops->resource_unload(&surface->resource);
if (surface->pow2Width != swapchain_desc->backbuffer_width
|| surface->pow2Height != swapchain_desc->backbuffer_height)
{
surface->flags |= SFLAG_NONPOW2;
}
else
{
surface->flags &= ~SFLAG_NONPOW2;
}
HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
surface->resource.allocatedMemory = NULL;
surface->resource.heapMemory = NULL;
surface->resource.size = wined3d_surface_get_pitch(surface) * surface->pow2Width;
/* Put all surfaces into sysmem - the drawable might disappear if the backbuffer was rendered
* to a FBO */
if (!surface_init_sysmem(surface))
{
return E_OUTOFMEMORY;
}
return WINED3D_OK;
}
static BOOL is_display_mode_supported(const struct wined3d_device *device, static BOOL is_display_mode_supported(const struct wined3d_device *device,
const struct wined3d_swapchain_desc *swapchain_desc) const struct wined3d_swapchain_desc *swapchain_desc)
{ {
@ -5580,7 +5517,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
{ {
UINT i; UINT i;
hr = updateSurfaceDesc(swapchain->front_buffer, &swapchain->desc); hr = wined3d_surface_update_desc(swapchain->front_buffer, swapchain->desc.backbuffer_width,
swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
swapchain->desc.multisample_type, swapchain->desc.multisample_quality);
if (FAILED(hr)) if (FAILED(hr))
{ {
wined3d_swapchain_decref(swapchain); wined3d_swapchain_decref(swapchain);
@ -5589,7 +5528,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
for (i = 0; i < swapchain->desc.backbuffer_count; ++i) for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
{ {
hr = updateSurfaceDesc(swapchain->back_buffers[i], &swapchain->desc); hr = wined3d_surface_update_desc(swapchain->back_buffers[i], swapchain->desc.backbuffer_width,
swapchain->desc.backbuffer_height, swapchain->desc.backbuffer_format,
swapchain->desc.multisample_type, swapchain->desc.multisample_quality);
if (FAILED(hr)) if (FAILED(hr))
{ {
wined3d_swapchain_decref(swapchain); wined3d_swapchain_decref(swapchain);
@ -5598,7 +5539,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
} }
if (device->auto_depth_stencil) if (device->auto_depth_stencil)
{ {
hr = updateSurfaceDesc(device->auto_depth_stencil, &swapchain->desc); hr = wined3d_surface_update_desc(device->auto_depth_stencil, swapchain->desc.backbuffer_width,
swapchain->desc.backbuffer_height, device->auto_depth_stencil->resource.format->id,
swapchain->desc.multisample_type, swapchain->desc.multisample_quality);
if (FAILED(hr)) if (FAILED(hr))
{ {
wined3d_swapchain_decref(swapchain); wined3d_swapchain_decref(swapchain);

View File

@ -3314,6 +3314,70 @@ HRESULT CDECL wined3d_surface_update_overlay(struct wined3d_surface *surface, co
return WINED3D_OK; return WINED3D_OK;
} }
HRESULT CDECL wined3d_surface_update_desc(struct wined3d_surface *surface,
UINT width, UINT height, enum wined3d_format_id format_id,
enum wined3d_multisample_type multisample_type, UINT multisample_quality)
{
struct wined3d_device *device = surface->resource.device;
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
const struct wined3d_format *format = wined3d_get_format(gl_info, format_id);
UINT resource_size = wined3d_format_calculate_size(format, device->surface_alignment, width, height);
TRACE("surface %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u.\n",
surface, width, height, debug_d3dformat(format_id), multisample_type, multisample_type);
if (!resource_size)
return WINED3DERR_INVALIDCALL;
if (device->d3d_initialized)
surface->resource.resource_ops->resource_unload(&surface->resource);
if (surface->flags & SFLAG_DIBSECTION)
{
DeleteDC(surface->hDC);
DeleteObject(surface->dib.DIBsection);
surface->dib.bitmap_data = NULL;
surface->flags &= ~SFLAG_DIBSECTION;
}
surface->flags &= ~(SFLAG_LOCATIONS | SFLAG_USERPTR);
surface->resource.allocatedMemory = NULL;
HeapFree(GetProcessHeap(), 0, surface->resource.heapMemory);
surface->resource.heapMemory = NULL;
surface->resource.width = width;
surface->resource.height = height;
if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] || gl_info->supported[ARB_TEXTURE_RECTANGLE]
|| gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
{
surface->pow2Width = width;
surface->pow2Height = height;
}
else
{
surface->pow2Width = surface->pow2Height = 1;
while (surface->pow2Width < width)
surface->pow2Width <<= 1;
while (surface->pow2Height < height)
surface->pow2Height <<= 1;
}
if (surface->pow2Width != width || surface->pow2Height != height)
surface->flags |= SFLAG_NONPOW2;
else
surface->flags &= ~SFLAG_NONPOW2;
surface->resource.format = format;
surface->resource.multisample_type = multisample_type;
surface->resource.multisample_quality = multisample_quality;
surface->resource.size = resource_size;
if (!surface_init_sysmem(surface))
return E_OUTOFMEMORY;
return WINED3D_OK;
}
HRESULT CDECL wined3d_surface_set_format(struct wined3d_surface *surface, enum wined3d_format_id format_id) HRESULT CDECL wined3d_surface_set_format(struct wined3d_surface *surface, enum wined3d_format_id format_id)
{ {
const struct wined3d_format *format = wined3d_get_format(&surface->resource.device->adapter->gl_info, format_id); const struct wined3d_format *format = wined3d_get_format(&surface->resource.device->adapter->gl_info, format_id);

View File

@ -217,6 +217,7 @@
@ cdecl wined3d_surface_set_palette(ptr ptr) @ cdecl wined3d_surface_set_palette(ptr ptr)
@ cdecl wined3d_surface_set_priority(ptr long) @ cdecl wined3d_surface_set_priority(ptr long)
@ cdecl wined3d_surface_unmap(ptr) @ cdecl wined3d_surface_unmap(ptr)
@ cdecl wined3d_surface_update_desc(ptr long long long long long)
@ cdecl wined3d_surface_update_overlay(ptr ptr ptr ptr long ptr) @ cdecl wined3d_surface_update_overlay(ptr ptr ptr ptr long ptr)
@ cdecl wined3d_surface_update_overlay_z_order(ptr long ptr) @ cdecl wined3d_surface_update_overlay_z_order(ptr long ptr)

View File

@ -2334,6 +2334,9 @@ HRESULT __cdecl wined3d_surface_set_overlay_position(struct wined3d_surface *sur
HRESULT __cdecl wined3d_surface_set_palette(struct wined3d_surface *surface, struct wined3d_palette *palette); HRESULT __cdecl wined3d_surface_set_palette(struct wined3d_surface *surface, struct wined3d_palette *palette);
DWORD __cdecl wined3d_surface_set_priority(struct wined3d_surface *surface, DWORD new_priority); DWORD __cdecl wined3d_surface_set_priority(struct wined3d_surface *surface, DWORD new_priority);
HRESULT __cdecl wined3d_surface_unmap(struct wined3d_surface *surface); HRESULT __cdecl wined3d_surface_unmap(struct wined3d_surface *surface);
HRESULT __cdecl wined3d_surface_update_desc(struct wined3d_surface *surface,
UINT width, UINT height, enum wined3d_format_id format_id,
enum wined3d_multisample_type multisample_type, UINT multisample_quality);
HRESULT __cdecl wined3d_surface_update_overlay(struct wined3d_surface *surface, const RECT *src_rect, HRESULT __cdecl wined3d_surface_update_overlay(struct wined3d_surface *surface, const RECT *src_rect,
struct wined3d_surface *dst_surface, const RECT *dst_rect, DWORD flags, const WINEDDOVERLAYFX *fx); struct wined3d_surface *dst_surface, const RECT *dst_rect, DWORD flags, const WINEDDOVERLAYFX *fx);
HRESULT __cdecl wined3d_surface_update_overlay_z_order(struct wined3d_surface *surface, HRESULT __cdecl wined3d_surface_update_overlay_z_order(struct wined3d_surface *surface,