From afb64506ba0eb958af72d8535d8c5473f7fcc06e Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Thu, 12 Jan 2012 21:43:08 +0100 Subject: [PATCH] ddraw: Implement width and height changes in ddraw_surface7_SetSurfaceDesc(). --- dlls/ddraw/surface.c | 66 ++++++++++++++++++++++++++++++--------- dlls/ddraw/tests/dsurface.c | 8 ++--- dlls/wined3d/device.c | 75 ++++++--------------------------------------- dlls/wined3d/surface.c | 64 ++++++++++++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 3 ++ 6 files changed, 133 insertions(+), 84 deletions(-) diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c index 0d6e398ece2..dec5612b1f5 100644 --- a/dlls/ddraw/surface.c +++ b/dlls/ddraw/surface.c @@ -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) { IDirectDrawSurfaceImpl *This = impl_from_IDirectDrawSurface7(iface); - enum wined3d_format_id newFormat = WINED3DFMT_UNKNOWN; HRESULT hr; const DWORD allowed_flags = DDSD_LPSURFACE | DDSD_PIXELFORMAT | DDSD_WIDTH | 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); @@ -4177,18 +4179,26 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, } 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) { - 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) { WARN("DDSD_PITCH is set, but DDSD_WIDTH is not, returning DDERR_INVALIDPARAMS.\n"); return DDERR_INVALIDPARAMS; } + else + { + width = This->surface_desc.dwWidth; + } + if (DDSD->dwFlags & DDSD_HEIGHT) { if (!DDSD->dwHeight) @@ -4198,32 +4208,60 @@ static HRESULT WINAPI ddraw_surface7_SetSurfaceDesc(IDirectDrawSurface7 *iface, } 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(); 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"); wined3d_mutex_unlock(); 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); - if (FAILED(hr)) - { - wined3d_mutex_unlock(); - return hr; - } - This->surface_desc.u4.ddpfPixelFormat = DDSD->u4.ddpfPixelFormat; + TRACE("Surface format changed from %#x to %#x.\n", current_format_id, format_id); + update_wined3d = TRUE; } } + 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) { hr = wined3d_surface_set_mem(This->wined3d_surface, DDSD->lpSurface); diff --git a/dlls/ddraw/tests/dsurface.c b/dlls/ddraw/tests/dsurface.c index 32af27e1f97..85a5d7a5a70 100644 --- a/dlls/ddraw/tests/dsurface.c +++ b/dlls/ddraw/tests/dsurface.c @@ -4580,7 +4580,7 @@ static void set_surface_desc_test(void) hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd); ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr); 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 */ reset_ddsd(&ddsd); @@ -4612,9 +4612,9 @@ static void set_surface_desc_test(void) reset_ddsd(&ddsd); hr = IDirectDrawSurface3_GetSurfaceDesc(surface3, &ddsd); ok(SUCCEEDED(hr), "GetSurfaceDesc failed, hr %#x.\n", hr); - todo_wine 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); - todo_wine ok(U1(ddsd).lPitch == 16 * 4, "SetSurfaceDesc: Expected pitch 64, got %u.\n", U1(ddsd).lPitch); + ok(ddsd.dwWidth == 16, "SetSurfaceDesc: Expected width 8, got %u.\n", ddsd.dwWidth); + ok(ddsd.dwHeight == 16, "SetSurfaceDesc: Expected height 16, got %u.\n", ddsd.dwHeight); + 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 * diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 563a9245bcb..6b3593a6e33 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -5200,69 +5200,6 @@ void CDECL wined3d_device_evict_managed_resources(struct wined3d_device *device) 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, const struct wined3d_swapchain_desc *swapchain_desc) { @@ -5580,7 +5517,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, { 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)) { 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) { - 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)) { wined3d_swapchain_decref(swapchain); @@ -5598,7 +5539,9 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device, } 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)) { wined3d_swapchain_decref(swapchain); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 3b21f878f4c..2cf01f988e9 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -3314,6 +3314,70 @@ HRESULT CDECL wined3d_surface_update_overlay(struct wined3d_surface *surface, co 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) { const struct wined3d_format *format = wined3d_get_format(&surface->resource.device->adapter->gl_info, format_id); diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 0b25f7c2c10..8279aa6fd54 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -217,6 +217,7 @@ @ cdecl wined3d_surface_set_palette(ptr ptr) @ cdecl wined3d_surface_set_priority(ptr long) @ 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_z_order(ptr long ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 5366c18be08..b423dd8cae9 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -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); 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_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, 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, -- 2.11.4.GIT