Stefan Dösinger : ddraw: Support using an application-provided surface pointer.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jul 26 09:00:50 CDT 2006


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

Author: Stefan Dösinger <stefandoesinger at gmx.at>
Date:   Tue Jul 25 16:38:02 2006 +0200

ddraw: Support using an application-provided surface pointer.

---

 dlls/ddraw/ddraw.c               |   17 ++++++++-----
 dlls/ddraw/surface.c             |    9 +++++++
 dlls/wined3d/surface.c           |   50 ++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/surface_gdi.c       |   13 ++++++++++
 dlls/wined3d/wined3d_private.h   |    6 +++--
 include/wine/wined3d_interface.h |    2 ++
 6 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index bd13d56..44fe5a0 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -1790,13 +1790,6 @@ IDirectDrawImpl_CreateNewSurface(IDirect
         }
     }
 
-    /* Get the surface parameters */
-    if ( pDDSD->dwFlags & DDSD_LPSURFACE)
-    {
-        ERR("(%p) Using a passed surface pointer is not yet supported\n", This);
-	assert(0);
-    }
-
     /* Get the correct wined3d usage */
     if (pDDSD->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE |
                                  DDSCAPS_BACKBUFFER     |
@@ -1995,6 +1988,16 @@ IDirectDrawImpl_CreateNewSurface(IDirect
                                     DDCKEY_SRCBLT,
                                     &pDDSD->ddckCKSrcBlt);
     }
+    if ( pDDSD->dwFlags & DDSD_LPSURFACE)
+    {
+        hr = IWineD3DSurface_SetMem((*ppSurf)->WineD3DSurface, pDDSD->lpSurface);
+        if(hr != WINED3D_OK)
+        {
+            /* No need for a trace here, wined3d does that for us */
+            IDirectDrawSurface7_Release(ICOM_INTERFACE((*ppSurf), IDirectDrawSurface7));
+            return hr;
+        }
+    }
 
     return DD_OK;
 }
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index a9086d2..587a3e9 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -1933,6 +1933,15 @@ IDirectDrawSurfaceImpl_SetSurfaceDesc(ID
                                     DDCKEY_SRCBLT,
                                     &DDSD->ddckCKSrcBlt);
     }
+    if (DDSD->dwFlags & DDSD_LPSURFACE)
+    {
+        hr = IWineD3DSurface_SetMem(This->WineD3DSurface, DDSD->lpSurface);
+        if(hr != WINED3D_OK)
+        {
+            /* No need for a trace here, wined3d does that for us */
+            return hr;
+        }
+    }
 
     This->surface_desc = *DDSD;
 
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 9c2ed60..df35fc6 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -102,6 +102,7 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release
             This->dib.bitmap_data = NULL;
             This->resource.allocatedMemory = NULL;
         }
+        IWineD3DSurface_SetMem(iface, NULL);
 
         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
         if(iface == device->ddraw_primary)
@@ -1161,6 +1162,11 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC
 
     TRACE("(%p)->(%p)\n",This,pHDC);
 
+    if(This->Flags & SFLAG_USERPTR) {
+        ERR("Not supported on surfaces with an application-provided surfaces\n");
+        return DDERR_NODC;
+    }
+
     /* Give more detailed info for ddraw */
     if (This->Flags & SFLAG_DCINUSE)
         return DDERR_DCALREADYCREATED;
@@ -2104,6 +2110,49 @@ HRESULT WINAPI IWineD3DSurfaceImpl_SetFo
     return WINED3D_OK;
 }
 
+HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
+    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
+
+    /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
+    if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
+        ERR("Not supported on render targets\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
+        WARN("Surface is locked or the HDC is in use\n");
+        return WINED3DERR_INVALIDCALL;
+    }
+
+    if(Mem && Mem != This->resource.allocatedMemory) {
+
+        /* Do I have to copy the old surface content? */
+        if(This->Flags & SFLAG_DIBSECTION) {
+                /* Release the DC. No need to hold the critical section for the update
+                 * Thread because this thread runs only on front buffers, but this method
+                 * fails for render targets in the check above.
+                 */
+                SelectObject(This->hDC, This->dib.holdbitmap);
+                DeleteDC(This->hDC);
+                /* Release the DIB section */
+                DeleteObject(This->dib.DIBsection);
+                This->dib.bitmap_data = NULL;
+                This->resource.allocatedMemory = NULL;
+                This->hDC = NULL;
+                This->Flags &= ~SFLAG_DIBSECTION;
+        } else if(!(This->Flags & SFLAG_USERPTR)) {
+            HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
+        }
+        This->resource.allocatedMemory = Mem;
+        This->Flags |= SFLAG_USERPTR;
+    } else if(This->Flags & SFLAG_USERPTR) {
+        /* Lockrect and GetDC will re-create the dib section and allocated memory */
+        This->resource.allocatedMemory = NULL;
+        This->Flags &= ~SFLAG_USERPTR;
+    }
+    return WINED3D_OK;
+}
+
 /* TODO: replace this function with context management routines */
 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
@@ -2975,6 +3024,7 @@ const IWineD3DSurfaceVtbl IWineD3DSurfac
     IWineD3DSurfaceImpl_RealizePalette,
     IWineD3DSurfaceImpl_SetColorKey,
     IWineD3DSurfaceImpl_GetPitch,
+    IWineD3DSurfaceImpl_SetMem,
     /* Internal use: */
     IWineD3DSurfaceImpl_CleanDirtyRect,
     IWineD3DSurfaceImpl_AddDirtyRect,
diff --git a/dlls/wined3d/surface_gdi.c b/dlls/wined3d/surface_gdi.c
index bb07afa..9609ebd 100644
--- a/dlls/wined3d/surface_gdi.c
+++ b/dlls/wined3d/surface_gdi.c
@@ -178,6 +178,18 @@ IWineGDISurfaceImpl_LockRect(IWineD3DSur
     TRACE("(%p) : rect@%p flags(%08lx), output lockedRect@%p, memory@%p\n",
           This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
 
+    if(!This->resource.allocatedMemory) {
+        HDC hdc;
+        HRESULT hr;
+        /* This happens on gdi surfaces if the application set a user pointer and resets it.
+         * Recreate the DIB section
+         */
+        hr = IWineD3DSurface_GetDC(iface, &hdc);  /* will recursively call lockrect, do not set the LOCKED flag to this line */
+        if(hr != WINED3D_OK) return hr;
+        hr = IWineD3DSurface_ReleaseDC(iface, hdc);
+        if(hr != WINED3D_OK) return hr;
+    }
+
     pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
 
     if (NULL == pRect)
@@ -1570,6 +1582,7 @@ const IWineD3DSurfaceVtbl IWineGDISurfac
     IWineD3DSurfaceImpl_RealizePalette,
     IWineD3DSurfaceImpl_SetColorKey,
     IWineD3DSurfaceImpl_GetPitch,
+    IWineD3DSurfaceImpl_SetMem,
     /* Internal use: */
     IWineD3DSurfaceImpl_CleanDirtyRect,
     IWineD3DSurfaceImpl_AddDirtyRect,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1f51e3b..d0fb485 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -929,6 +929,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC
 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC);
 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface);
 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface);
+HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem);
 
 /* Surface flags: */
 #define SFLAG_OVERSIZE    0x00000001 /* Surface is bigger than gl size, blts only */
@@ -948,7 +949,7 @@ #define SFLAG_DCINUSE     0x00002000 /* 
 #define SFLAG_GLDIRTY     0x00004000 /* The opengl texture is more up to date than the surface mem */
 #define SFLAG_LOST        0x00008000 /* Surface lost flag for DDraw */
 #define SFLAG_FORCELOAD   0x00010000 /* To force PreLoading of a scratch cursor */
-
+#define SFLAG_USERPTR     0x00020000 /* The application allocated the memory for this surface */
 
 /* In some conditions the surface memory must not be freed:
  * SFLAG_OVERSIZE: Not all data can be kept in GL
@@ -967,7 +968,8 @@ #define SFLAG_DONOTFREE  (SFLAG_OVERSIZE
                           SFLAG_LOCKED     | \
                           SFLAG_ACTIVELOCK | \
                           SFLAG_DYNLOCK    | \
-                          SFLAG_DYNCHANGE    )
+                          SFLAG_DYNCHANGE  | \
+                          SFLAG_USERPTR)
 
 BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]);
 
diff --git a/include/wine/wined3d_interface.h b/include/wine/wined3d_interface.h
index 1c97114..2104aaa 100644
--- a/include/wine/wined3d_interface.h
+++ b/include/wine/wined3d_interface.h
@@ -1130,6 +1130,7 @@ DECLARE_INTERFACE_(IWineD3DSurface,IWine
     STDMETHOD(RealizePalette)(THIS) PURE;
     STDMETHOD(SetColorKey)(THIS_ DWORD Flags, DDCOLORKEY *CKey) PURE;
     STDMETHOD_(DWORD,GetPitch)(THIS) PURE;
+    STDMETHOD(SetMem)(THIS_ void *mem) PURE;
     /* Internally used methods */
     STDMETHOD(CleanDirtyRect)(THIS) PURE;
     STDMETHOD(AddDirtyRect)(THIS_ CONST RECT* pRect) PURE;
@@ -1181,6 +1182,7 @@ #define IWineD3DSurface_SetPalette(p, a)
 #define IWineD3DSurface_RealizePalette(p)            (p)->lpVtbl->RealizePalette(p)
 #define IWineD3DSurface_SetColorKey(p, a, b)         (p)->lpVtbl->SetColorKey(p, a, b)
 #define IWineD3DSurface_GetPitch(p)                  (p)->lpVtbl->GetPitch(p)
+#define IWineD3DSurface_SetMem(p, a)                 (p)->lpVtbl->SetMem(p, a)
 /*** IWineD3DSurface (Internal, no d3d mapping) methods ***/
 #define IWineD3DSurface_CleanDirtyRect(p)            (p)->lpVtbl->CleanDirtyRect(p)
 #define IWineD3DSurface_AddDirtyRect(p,a)            (p)->lpVtbl->AddDirtyRect(p,a)




More information about the wine-cvs mailing list