[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    RFC: d3d9: Increment the reference count of the IDirect3D9 instance
From:       Andrew Nguyen <anguyen () codeweavers ! com>
Date:       2011-05-31 11:55:21
Message-ID: 4DE4D729.40702 () codeweavers ! com
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


The Pathologic demo in bug 21552 expects that the reference count of a
IDirect3D9 instance is incremented after a successful call to
CreateDevice with the instance.

Does my proposed fix for d3d8 and d3d9 manage the reference count of the
device parent appropriately? In particular, I'm concerned about the
slightly cumbersome acquisition of the pointer to the parent instance
within the Release call for the Direct3D device interface. Is the
overall location of the AddRef/Release calls correct, and should I be
doing something differently when the device tries to decrement the
parent reference count?

["0001-d3d8-Increment-the-reference-count-of-the-IDirect3D8-i.txt" (text/plain)]

From 8f10b990eac571f10dc376e07096cfc5368dd0e9 Mon Sep 17 00:00:00 2001
From: Andrew Nguyen <anguyen@codeweavers.com>
Date: Thu, 26 May 2011 22:27:26 -0500
Subject: d3d8: Increment the reference count of the IDirect3D8 instance when
 creating a device.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/d3d8/device.c       |   14 ++++++++++++++
 dlls/d3d8/directx.c      |    1 +
 dlls/d3d8/tests/device.c |   12 ++++++++++++
 3 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index aa85c61..87fce9d 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -301,6 +301,9 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(IDirect3DDevice8 *iface)
 
     if (ref == 0) {
         unsigned i;
+        HRESULT hr;
+        struct wined3d *wined3d;
+        IDirect3D8 *pD3D8 = NULL;
 
         TRACE("Releasing wined3d device %p.\n", This->wined3d_device);
 
@@ -313,6 +316,14 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(IDirect3DDevice8 *iface)
         }
         HeapFree(GetProcessHeap(), 0, This->decls);
 
+        /* Get the parent IDirect3D8 instance. */
+        hr = wined3d_device_get_wined3d(This->wined3d_device, &wined3d);
+        if (hr == S_OK && wined3d)
+        {
+            pD3D8 = wined3d_get_parent(wined3d);
+            wined3d_decref(wined3d);
+        }
+
         wined3d_device_uninit_3d(This->wined3d_device);
         wined3d_device_release_focus_window(This->wined3d_device);
         wined3d_device_decref(This->wined3d_device);
@@ -320,6 +331,9 @@ static ULONG WINAPI IDirect3DDevice8Impl_Release(IDirect3DDevice8 *iface)
         HeapFree(GetProcessHeap(), 0, This);
 
         wined3d_mutex_unlock();
+
+        if (pD3D8)
+            IDirect3D8_Release(pD3D8);
     }
     return ref;
 }
diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c
index 249399e..3ec821e 100644
--- a/dlls/d3d8/directx.c
+++ b/dlls/d3d8/directx.c
@@ -379,6 +379,7 @@ static HRESULT WINAPI IDirect3D8Impl_CreateDevice(IDirect3D8 *iface, UINT adapte
     TRACE("Created device %p.\n", object);
     *device = &object->IDirect3DDevice8_iface;
 
+    IDirect3D8_AddRef(iface);
     return D3D_OK;
 }
 
diff --git a/dlls/d3d8/tests/device.c b/dlls/d3d8/tests/device.c
index 3bb70b7..9a4369b 100644
--- a/dlls/d3d8/tests/device.c
+++ b/dlls/d3d8/tests/device.c
@@ -343,6 +343,7 @@ static void test_refcount(void)
     HRESULT                      hr;
     HWND                         hwnd               = NULL;
     IDirect3D8                  *pD3d               = NULL;
+    IDirect3D8                  *pD3d2              = NULL;
     IDirect3DDevice8            *pDevice            = NULL;
     IDirect3DVertexBuffer8      *pVertexBuffer      = NULL;
     IDirect3DIndexBuffer8       *pIndexBuffer       = NULL;
@@ -381,6 +382,8 @@ static void test_refcount(void)
     ok(hwnd != NULL, "Failed to create window\n");
     if (!pD3d || !hwnd) goto cleanup;
 
+    CHECK_REFCOUNT( pD3d, 1 );
+
     IDirect3D8_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
     ZeroMemory( &d3dpp, sizeof(d3dpp) );
     d3dpp.Windowed         = TRUE;
@@ -401,6 +404,15 @@ static void test_refcount(void)
     refcount = get_refcount( (IUnknown *)pDevice );
     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
 
+    CHECK_REFCOUNT( pD3d, 2 );
+
+    hr = IDirect3DDevice8_GetDirect3D(pDevice, &pD3d2);
+    CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
+
+    ok(pD3d2 == pD3d, "Expected IDirect3D8 pointers to be equal\n");
+    CHECK_REFCOUNT( pD3d, 3 );
+    CHECK_RELEASE_REFCOUNT( pD3d, 2 );
+
     /**
      * Check refcount of implicit surfaces. Findings:
      *   - the container is the device
-- 
1.7.5.2


["0002-d3d9-Increment-the-reference-count-of-the-IDirect3D9-i.txt" (text/plain)]

From c509cbcfdb5a8092ea530b6a8940c98e0f6bd0e9 Mon Sep 17 00:00:00 2001
From: Andrew Nguyen <anguyen@codeweavers.com>
Date: Thu, 26 May 2011 22:50:31 -0500
Subject: d3d9: Increment the reference count of the IDirect3D9 instance when
 creating a device.
To: wine-patches <wine-patches@winehq.org>
Reply-To: wine-devel <wine-devel@winehq.org>

---
 dlls/d3d9/device.c       |   15 +++++++++++++++
 dlls/d3d9/directx.c      |    2 ++
 dlls/d3d9/tests/device.c |   12 ++++++++++++
 3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index a95fa16..a7ce3ac 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -249,6 +249,10 @@ static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevi
 
     if (ref == 0) {
       unsigned i;
+      HRESULT hr;
+      struct wined3d *wined3d;
+      IDirect3D9 *pD3D9 = NULL;
+
       This->inDestruction = TRUE;
 
       wined3d_mutex_lock();
@@ -260,12 +264,23 @@ static ULONG WINAPI DECLSPEC_HOTPATCH IDirect3DDevice9Impl_Release(IDirect3DDevi
       }
       HeapFree(GetProcessHeap(), 0, This->convertedDecls);
 
+      /* Get the parent IDirect3D9 instance. */
+      hr = wined3d_device_get_wined3d(This->wined3d_device, &wined3d);
+      if (hr == S_OK && wined3d)
+      {
+          pD3D9 = wined3d_get_parent(wined3d);
+          wined3d_decref(wined3d);
+      }
+
       wined3d_device_uninit_3d(This->wined3d_device);
       wined3d_device_release_focus_window(This->wined3d_device);
       wined3d_device_decref(This->wined3d_device);
       wined3d_mutex_unlock();
 
       HeapFree(GetProcessHeap(), 0, This);
+
+      if (pD3D9)
+          IDirect3D9_Release(pD3D9);
     }
     return ref;
 }
diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c
index 791d835..f638453 100644
--- a/dlls/d3d9/directx.c
+++ b/dlls/d3d9/directx.c
@@ -460,6 +460,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3D9Impl_CreateDevice(IDirect3D9Ex
     TRACE("Created device %p.\n", object);
     *device = (IDirect3DDevice9 *)object;
 
+    IDirect3D9_AddRef(iface);
     return D3D_OK;
 }
 
@@ -518,6 +519,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH IDirect3D9ExImpl_CreateDeviceEx(IDirect3
     TRACE("Created device %p.\n", object);
     *device = &object->IDirect3DDevice9Ex_iface;
 
+    IDirect3D9_AddRef(iface);
     return D3D_OK;
 }
 
diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c
index 1a74d6e..235b06f 100644
--- a/dlls/d3d9/tests/device.c
+++ b/dlls/d3d9/tests/device.c
@@ -423,6 +423,7 @@ static void test_refcount(void)
     HRESULT                      hr;
     HWND                         hwnd               = NULL;
     IDirect3D9                  *pD3d               = NULL;
+    IDirect3D9                  *pD3d2              = NULL;
     IDirect3DDevice9            *pDevice            = NULL;
     IDirect3DVertexBuffer9      *pVertexBuffer      = NULL;
     IDirect3DIndexBuffer9       *pIndexBuffer       = NULL;
@@ -467,6 +468,8 @@ static void test_refcount(void)
     ok(hwnd != NULL, "Failed to create window\n");
     if (!pD3d || !hwnd) goto cleanup;
 
+    CHECK_REFCOUNT( pD3d, 1 );
+
     IDirect3D9_GetAdapterDisplayMode( pD3d, D3DADAPTER_DEFAULT, &d3ddm );
     ZeroMemory( &d3dpp, sizeof(d3dpp) );
     d3dpp.Windowed         = TRUE;
@@ -484,6 +487,15 @@ static void test_refcount(void)
     refcount = get_refcount( (IUnknown *)pDevice );
     ok(refcount == 1, "Invalid device RefCount %d\n", refcount);
 
+    CHECK_REFCOUNT( pD3d, 2 );
+
+    hr = IDirect3DDevice9_GetDirect3D(pDevice, &pD3d2);
+    CHECK_CALL( hr, "GetDirect3D", pDevice, refcount );
+
+    ok(pD3d2 == pD3d, "Expected IDirect3D9 pointers to be equal\n");
+    CHECK_REFCOUNT( pD3d, 3 );
+    CHECK_RELEASE_REFCOUNT( pD3d, 2 );
+
     /**
      * Check refcount of implicit surfaces and implicit swapchain. Findings:
      *   - the container is the device OR swapchain
-- 
1.7.5.2


["signature.asc" (application/pgp-signature)]



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic