wined3d: The cursor image surface is not allowed to be NULL in wined3d_device_set_cursor_properties().
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
51b9aba9cc
commit
8b9e56cc9e
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue