Stefan Dösinger : wined3d: Do not use the IWineD3DSurface for the cursor.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jul 28 07:15:06 CDT 2006


Module: wine
Branch: refs/heads/master
Commit: 65e5ed60ae02f01015222a4317770a0444d36549
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=65e5ed60ae02f01015222a4317770a0444d36549

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Thu Jul 27 17:39:03 2006 +0200

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 83754c2..651d134 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2115,6 +2115,14 @@ static HRESULT WINAPI IWineD3DDeviceImpl
 
     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  IWineD3DDeviceIm
     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  IWineD3DDeviceIm
         }
 
         /* 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 9dde987..f0b3033 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -142,17 +142,40 @@ static HRESULT WINAPI IWineD3DSwapChainI
     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 f4ae19d..5329e42 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -540,7 +540,8 @@ #define                         NEEDS_DI
     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];




More information about the wine-cvs mailing list