wined3d: Add hardware cursor support.

This commit is contained in:
Andrew Riedi 2007-05-14 15:37:53 -07:00 committed by Alexandre Julliard
parent 52ca3ebada
commit a9c2e15cf6
4 changed files with 121 additions and 57 deletions

View file

@ -8,6 +8,7 @@
* Copyright 2005 Oliver Stieber
* Copyright 2006 Stefan Dösinger for CodeWeavers
* Copyright 2006-2007 Henri Verbeet
* Copyright 2007 Andrew Riedi
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -223,6 +224,8 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
}
if(This->contexts) ERR("Context array not freed!\n");
if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
This->haveHardwareCursor = FALSE;
IWineD3D_Release(This->wineD3D);
This->wineD3D = NULL;
@ -578,7 +581,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface,
return WINED3D_OK;
}
/* ************************************
MSDN:
[in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
@ -5702,6 +5704,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
/* TODO: the use of Impl is deprecated. */
IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
WINED3DLOCKED_RECT lockedRect;
TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
@ -5714,6 +5717,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i
This->cursorTexture = 0;
}
if ( (pSur->currentDesc.Width == 32) && (pSur->currentDesc.Height == 32) )
This->haveHardwareCursor = TRUE;
else
This->haveHardwareCursor = FALSE;
if(pCursorBitmap) {
WINED3DLOCKED_RECT rect;
@ -5730,67 +5738,107 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i
return WINED3DERR_INVALIDCALL;
}
/* TODO: MSDN: Cursor sizes must be a power of 2 */
if (!This->haveHardwareCursor) {
/* 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. Copy out the gl texture instead.
*/
This->cursorWidth = pSur->currentDesc.Width;
This->cursorHeight = pSur->currentDesc.Height;
if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
{
const PixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8);
char *mem, *bits = (char *)rect.pBits;
GLint intfmt = tableEntry->glInternal;
GLint format = tableEntry->glFormat;
GLint type = tableEntry->glType;
INT height = This->cursorHeight;
INT width = This->cursorWidth;
INT bpp = tableEntry->bpp;
INT i;
/* 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. Copy out the gl texture
* instead.
*/
This->cursorWidth = pSur->currentDesc.Width;
This->cursorHeight = pSur->currentDesc.Height;
if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
{
const PixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8);
char *mem, *bits = (char *)rect.pBits;
GLint intfmt = tableEntry->glInternal;
GLint format = tableEntry->glFormat;
GLint type = tableEntry->glType;
INT height = This->cursorHeight;
INT width = This->cursorWidth;
INT bpp = tableEntry->bpp;
INT i;
/* Reformat the texture memory (pitch and width can be different) */
mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
for(i = 0; i < height; i++)
memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
IWineD3DSurface_UnlockRect(pCursorBitmap);
ENTER_GL();
/* Reformat the texture memory (pitch and width can be
* different) */
mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
for(i = 0; i < height; i++)
memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
IWineD3DSurface_UnlockRect(pCursorBitmap);
ENTER_GL();
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
}
/* Make sure that a proper texture unit is selected */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB");
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
/* Create a new cursor texture */
glGenTextures(1, &This->cursorTexture);
checkGLcall("glGenTextures");
glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
checkGLcall("glBindTexture");
/* Copy the bitmap memory into the cursor texture */
glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
HeapFree(GetProcessHeap(), 0, mem);
checkGLcall("glTexImage2D");
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
}
LEAVE_GL();
}
/* Make sure that a proper texture unit is selected */
if (GL_SUPPORT(ARB_MULTITEXTURE)) {
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
checkGLcall("glActiveTextureARB");
else
{
FIXME("A cursor texture was not returned.\n");
This->cursorTexture = 0;
}
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
/* Create a new cursor texture */
glGenTextures(1, &This->cursorTexture);
checkGLcall("glGenTextures");
glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
checkGLcall("glBindTexture");
/* Copy the bitmap memory into the cursor texture */
glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
HeapFree(GetProcessHeap(), 0, mem);
checkGLcall("glTexImage2D");
if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
}
LEAVE_GL();
}
else
{
FIXME("A cursor texture was not returned.\n");
This->cursorTexture = 0;
}
/* Draw a hardware cursor */
ICONINFO cursorInfo;
HCURSOR cursor;
/* Create and clear maskBits because it is not needed for
* 32-bit cursors. 32x32 bits split into 32-bit chunks == 32
* chunks. */
DWORD *maskBits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
(pSur->currentDesc.Width * pSur->currentDesc.Height / 8));
IWineD3DSurface_LockRect(pCursorBitmap, &lockedRect, NULL,
WINED3DLOCK_NO_DIRTY_UPDATE |
WINED3DLOCK_READONLY
);
TRACE("width: %i height: %i\n", pSur->currentDesc.Width,
pSur->currentDesc.Height);
cursorInfo.fIcon = FALSE;
cursorInfo.xHotspot = XHotSpot;
cursorInfo.yHotspot = YHotSpot;
cursorInfo.hbmMask = CreateBitmap(pSur->currentDesc.Width,
pSur->currentDesc.Height, 1,
1, &maskBits);
cursorInfo.hbmColor = CreateBitmap(pSur->currentDesc.Width,
pSur->currentDesc.Height, 1,
32, lockedRect.pBits);
IWineD3DSurface_UnlockRect(pCursorBitmap);
/* Create our cursor and clean up. */
cursor = CreateIconIndirect(&cursorInfo);
SetCursor(cursor);
if (cursorInfo.hbmMask) DeleteObject(cursorInfo.hbmMask);
if (cursorInfo.hbmColor) DeleteObject(cursorInfo.hbmColor);
if (This->hardwareCursor) DestroyCursor(This->hardwareCursor);
This->hardwareCursor = cursor;
HeapFree(GetProcessHeap(), 0, maskBits);
}
}
This->xHotSpot = XHotSpot;
@ -5816,8 +5864,6 @@ static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOO
TRACE("(%p) : visible(%d)\n", This, bShow);
if(This->cursorTexture)
This->bCursorVisible = bShow;
/*
* When ShowCursor is first called it should make the cursor appear at the OS's last
* known cursor position. Because of this, some applications just repetitively call
@ -5827,6 +5873,19 @@ static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOO
This->xScreenSpace = pt.x;
This->yScreenSpace = pt.y;
if (This->haveHardwareCursor) {
This->bCursorVisible = bShow;
if (bShow)
SetCursor(This->hardwareCursor);
else
SetCursor(NULL);
}
else
{
if (This->cursorTexture)
This->bCursorVisible = bShow;
}
return oldVisible;
}

View file

@ -1928,8 +1928,8 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
*pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
*pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
*pCaps->CursorCaps = 0;
*pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
WINED3DCURSORCAPS_LOWRES;
*pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |

View file

@ -688,6 +688,8 @@ struct IWineD3DDeviceImpl
UINT yScreenSpace;
UINT cursorWidth, cursorHeight;
GLuint cursorTexture;
BOOL haveHardwareCursor;
HCURSOR hardwareCursor;
/* Textures for when no other textures are mapped */
UINT dummyTextureName[MAX_TEXTURES];

View file

@ -1449,6 +1449,9 @@ typedef enum _WINED3DSURFTYPE {
#define WINED3DVTXPCAPS_TEXGEN_SPHEREMAP 0x00000100L
#define WINED3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER 0x00000200L
#define WINED3DCURSORCAPS_COLOR 0x000000001
#define WINED3DCURSORCAPS_LOWRES 0x000000002
#define WINED3DDEVCAPS_FLOATTLVERTEX 0x000000001
#define WINED3DDEVCAPS_SORTINCREASINGZ 0x000000002
#define WINED3DDEVCAPS_SORTDECREASINGZ 0X000000004