From 65e5ed60ae02f01015222a4317770a0444d36549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Thu, 27 Jul 2006 17:39:03 +0200 Subject: [PATCH] wined3d: Do not use the IWineD3DSurface for the cursor. --- dlls/wined3d/device.c | 30 ++++++++++++++++++++++++----- dlls/wined3d/swapchain.c | 35 ++++++++++++++++++++++++++++------ dlls/wined3d/wined3d_private.h | 3 ++- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 83754c2437d..651d1349bc3 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2115,6 +2115,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface) { if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL; + /* Delete the mouse cursor texture */ + if(This->cursorTexture) { + ENTER_GL(); + glDeleteTextures(1, &This->cursorTexture); + LEAVE_GL(); + This->cursorTexture = 0; + } + for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) { IWineD3DDevice_SetTexture(iface, sampler, NULL); } @@ -7471,6 +7479,13 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot); /* some basic validation checks */ + if(This->cursorTexture) { + ENTER_GL(); + glDeleteTextures(1, &This->cursorTexture); + LEAVE_GL(); + This->cursorTexture = 0; + } + if(pCursorBitmap) { /* MSDN: Cursor must be A8R8G8B8 */ if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) { @@ -7486,19 +7501,24 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* i } /* TODO: MSDN: Cursor sizes must be a power of 2 */ - if(This->mouseCursor) { - ((IWineD3DSurfaceImpl *) This->mouseCursor)->Flags &= ~SFLAG_FORCELOAD; - } /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out * Texture and Blitting code to draw the cursor */ pSur->Flags |= SFLAG_FORCELOAD; + IWineD3DSurface_PreLoad(pCursorBitmap); + pSur->Flags &= ~SFLAG_FORCELOAD; + /* 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->cursorTexture = pSur->glDescription.textureName; + This->cursorWidth = pSur->currentDesc.Width; + This->cursorHeight = pSur->currentDesc.Height; + pSur->glDescription.textureName = 0; /* Prevent the texture from beeing changed or deleted */ } This->xHotSpot = XHotSpot; This->yHotSpot = YHotSpot; - - This->mouseCursor = pCursorBitmap; return WINED3D_OK; } diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 9dde98723ee..f0b303338d1 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -142,17 +142,40 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO ENTER_GL(); /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */ - if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->mouseCursor) { - IWineD3DSurfaceImpl *cursor = (IWineD3DSurfaceImpl *) This->wineD3DDevice->mouseCursor; + if(This->wineD3DDevice->bCursorVisible && This->wineD3DDevice->cursorTexture) { + IWineD3DSurfaceImpl cursor; RECT destRect = {This->wineD3DDevice->xScreenSpace - This->wineD3DDevice->xHotSpot, This->wineD3DDevice->yScreenSpace - This->wineD3DDevice->yHotSpot, - This->wineD3DDevice->xScreenSpace + cursor->currentDesc.Width - This->wineD3DDevice->xHotSpot, - This->wineD3DDevice->yScreenSpace + cursor->currentDesc.Height - This->wineD3DDevice->yHotSpot}; - TRACE("Rendering the cursor\n"); + This->wineD3DDevice->xScreenSpace + This->wineD3DDevice->cursorWidth - This->wineD3DDevice->xHotSpot, + This->wineD3DDevice->yScreenSpace + This->wineD3DDevice->cursorHeight - This->wineD3DDevice->yHotSpot}; + TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor); + /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by + * the application because we are only supposed to copy the information out. Using a fake surface + * allows to use the Blitting engine and avoid copying the whole texture -> render target blitting code. + */ + memset(&cursor, 0, sizeof(cursor)); + cursor.lpVtbl = &IWineD3DSurface_Vtbl; + cursor.resource.ref = 1; + cursor.resource.wineD3DDevice = This->wineD3DDevice; + cursor.resource.pool = WINED3DPOOL_SCRATCH; + cursor.resource.format = WINED3DFMT_A8R8G8B8; + cursor.resource.resourceType = WINED3DRTYPE_SURFACE; + cursor.glDescription.textureName = This->wineD3DDevice->cursorTexture; + cursor.glDescription.target = GL_TEXTURE_2D; + cursor.glDescription.level = 0; + cursor.currentDesc.Width = This->wineD3DDevice->cursorWidth; + cursor.currentDesc.Height = This->wineD3DDevice->cursorHeight; + cursor.glRect.left = 0; + cursor.glRect.top = 0; + cursor.glRect.right = cursor.currentDesc.Width; + cursor.glRect.bottom = cursor.currentDesc.Height; + /* The cursor must have pow2 sizes */ + cursor.pow2Width = cursor.currentDesc.Width; + cursor.pow2Height = cursor.currentDesc.Height; /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0, * which is exactly what we want :-) */ - IWineD3DSurface_Blt(This->backBuffer[0], &destRect, This->wineD3DDevice->mouseCursor, NULL, DDBLT_KEYSRC, NULL); + IWineD3DSurface_Blt(This->backBuffer[0], &destRect, (IWineD3DSurface *) &cursor, NULL, DDBLT_KEYSRC, NULL); } if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index f4ae19d5f7b..5329e42b0f6 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -540,7 +540,8 @@ typedef struct IWineD3DDeviceImpl UINT yHotSpot; UINT xScreenSpace; UINT yScreenSpace; - IWineD3DSurface *mouseCursor; + UINT cursorWidth, cursorHeight; + GLuint cursorTexture; /* Textures for when no other textures are mapped */ UINT dummyTextureName[MAX_TEXTURES];