From 8b9e56cc9e3d526e64e6fe7de664ed487875a0a6 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 16 Oct 2015 10:35:09 +0200 Subject: [PATCH] wined3d: The cursor image surface is not allowed to be NULL in wined3d_device_set_cursor_properties(). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/device.c | 152 +++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 75 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 4d1030d87f1..0d607ee7f6a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -4205,6 +4205,10 @@ static struct wined3d_texture *wined3d_device_create_cursor_texture(struct wined HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device, UINT x_hotspot, UINT y_hotspot, struct wined3d_surface *cursor_image) { + struct wined3d_display_mode mode; + struct wined3d_map_desc map_desc; + HRESULT hr; + TRACE("device %p, x_hotspot %u, y_hotspot %u, cursor_image %p.\n", device, x_hotspot, y_hotspot, cursor_image); @@ -4214,86 +4218,84 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device device->cursor_texture = NULL; } - if (cursor_image) + if (cursor_image->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM) { - struct wined3d_display_mode mode; - struct wined3d_map_desc map_desc; - HRESULT hr; - - /* MSDN: Cursor must be A8R8G8B8 */ - if (cursor_image->resource.format->id != WINED3DFMT_B8G8R8A8_UNORM) - { - WARN("surface %p has an invalid format.\n", cursor_image); - return WINED3DERR_INVALIDCALL; - } - - if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL))) - { - ERR("Failed to get display mode, hr %#x.\n", hr); - return WINED3DERR_INVALIDCALL; - } - - /* MSDN: Cursor must be smaller than the display mode */ - if (cursor_image->resource.width > mode.width || cursor_image->resource.height > mode.height) - { - WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n", - cursor_image, cursor_image->resource.width, cursor_image->resource.height, - mode.width, mode.height); - return WINED3DERR_INVALIDCALL; - } - - /* TODO: MSDN: Cursor sizes must be a power of 2 */ - - /* Do not store the surface's pointer because the application may - * release it after setting the cursor image. Windows doesn't - * addref the set surface, so we can't do this either without - * creating circular refcount dependencies. */ - if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image))) - { - ERR("Failed to create cursor texture.\n"); - return WINED3DERR_INVALIDCALL; - } - - device->cursorWidth = cursor_image->resource.width; - device->cursorHeight = cursor_image->resource.height; - - if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32) - { - UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8; - ICONINFO cursorInfo; - DWORD *maskBits; - HCURSOR cursor; - - /* 32-bit user32 cursors ignore the alpha channel if it's all - * zeroes, and use the mask instead. Fill the mask with all ones - * to ensure we still get a fully transparent cursor. */ - maskBits = HeapAlloc(GetProcessHeap(), 0, mask_size); - memset(maskBits, 0xff, mask_size); - wined3d_surface_map(cursor_image, &map_desc, NULL, - WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY); - TRACE("width: %u height: %u.\n", cursor_image->resource.width, cursor_image->resource.height); - - cursorInfo.fIcon = FALSE; - cursorInfo.xHotspot = x_hotspot; - cursorInfo.yHotspot = y_hotspot; - cursorInfo.hbmMask = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height, - 1, 1, maskBits); - cursorInfo.hbmColor = CreateBitmap(cursor_image->resource.width, cursor_image->resource.height, - 1, 32, map_desc.data); - wined3d_surface_unmap(cursor_image); - /* Create our cursor and clean up. */ - cursor = CreateIconIndirect(&cursorInfo); - if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask); - if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor); - if (device->hardwareCursor) DestroyCursor(device->hardwareCursor); - device->hardwareCursor = cursor; - if (device->bCursorVisible) SetCursor( cursor ); - HeapFree(GetProcessHeap(), 0, maskBits); - } + WARN("Surface %p has an invalid format %s.\n", + cursor_image, debug_d3dformat(cursor_image->resource.format->id)); + return WINED3DERR_INVALIDCALL; } + if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d, device->adapter->ordinal, &mode, NULL))) + { + ERR("Failed to get display mode, hr %#x.\n", hr); + return WINED3DERR_INVALIDCALL; + } + + if (cursor_image->resource.width > mode.width || cursor_image->resource.height > mode.height) + { + WARN("Surface %p dimensions are %ux%u, but screen dimensions are %ux%u.\n", + cursor_image, cursor_image->resource.width, cursor_image->resource.height, + mode.width, mode.height); + return WINED3DERR_INVALIDCALL; + } + + /* TODO: MSDN: Cursor sizes must be a power of 2 */ + + /* Do not store the surface's pointer because the application may + * release it after setting the cursor image. Windows doesn't + * addref the set surface, so we can't do this either without + * creating circular refcount dependencies. */ + if (!(device->cursor_texture = wined3d_device_create_cursor_texture(device, cursor_image))) + { + ERR("Failed to create cursor texture.\n"); + return WINED3DERR_INVALIDCALL; + } + + if (cursor_image->resource.width == 32 && cursor_image->resource.height == 32) + { + UINT mask_size = cursor_image->resource.width * cursor_image->resource.height / 8; + ICONINFO cursor_info; + DWORD *mask_bits; + HCURSOR cursor; + + /* 32-bit user32 cursors ignore the alpha channel if it's all + * zeroes, and use the mask instead. Fill the mask with all ones + * to ensure we still get a fully transparent cursor. */ + if (!(mask_bits = HeapAlloc(GetProcessHeap(), 0, mask_size))) + return E_OUTOFMEMORY; + memset(mask_bits, 0xff, mask_size); + + wined3d_surface_map(cursor_image, &map_desc, NULL, WINED3D_MAP_NO_DIRTY_UPDATE | WINED3D_MAP_READONLY); + cursor_info.fIcon = FALSE; + cursor_info.xHotspot = x_hotspot; + cursor_info.yHotspot = y_hotspot; + cursor_info.hbmMask = CreateBitmap(cursor_image->resource.width, + cursor_image->resource.height, 1, 1, mask_bits); + cursor_info.hbmColor = CreateBitmap(cursor_image->resource.width, + cursor_image->resource.height, 1, 32, map_desc.data); + wined3d_surface_unmap(cursor_image); + + /* Create our cursor and clean up. */ + cursor = CreateIconIndirect(&cursor_info); + if (cursor_info.hbmMask) + DeleteObject(cursor_info.hbmMask); + if (cursor_info.hbmColor) + DeleteObject(cursor_info.hbmColor); + if (device->hardwareCursor) + DestroyCursor(device->hardwareCursor); + device->hardwareCursor = cursor; + if (device->bCursorVisible) + SetCursor(cursor); + + HeapFree(GetProcessHeap(), 0, mask_bits); + } + + TRACE("New cursor dimensions are %ux%u.\n", cursor_image->resource.width, cursor_image->resource.height); + device->cursorWidth = cursor_image->resource.width; + device->cursorHeight = cursor_image->resource.height; device->xHotSpot = x_hotspot; device->yHotSpot = y_hotspot; + return WINED3D_OK; }