ac: initial Wave32 support in LLVM build helpers
[mesa.git] / src / gallium / state_trackers / nine / iunknown.c
index 541c528591aad4f0a812c12400ae7890f65ad050..3835651f5367ab5b224580eafc91e86ef35854af 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "nine_helpers.h"
 #include "nine_pdata.h"
+#include "nine_lock.h"
 
 #define DBG_CHANNEL DBG_UNKNOWN
 
@@ -33,9 +34,21 @@ HRESULT
 NineUnknown_ctor( struct NineUnknown *This,
                   struct NineUnknownParams *pParams )
 {
-    This->refs = pParams->container ? 0 : 1;
-    This->bind = 0;
-    This->forward = !This->refs;
+    if (pParams->container) {
+        This->refs = 0;
+        This->forward = true;
+        This->bind = 0;
+        assert(!pParams->start_with_bind_not_ref);
+    } else if (pParams->start_with_bind_not_ref) {
+        This->refs = 0;
+        This->forward = false;
+        This->bind = 1;
+    } else {
+        This->refs = 1;
+        This->forward = false;
+        This->bind = 0;
+    }
+
     This->container = pParams->container;
     This->device = pParams->device;
     if (This->refs && This->device)
@@ -78,6 +91,8 @@ NineUnknown_QueryInterface( struct NineUnknown *This,
     DBG("This=%p riid=%p id=%s ppvObject=%p\n",
         This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppvObject);
 
+    (void)guid_str;
+
     if (!ppvObject) return E_POINTER;
 
     do {
@@ -108,9 +123,6 @@ NineUnknown_AddRef( struct NineUnknown *This )
     if (r == 1) {
         if (This->device)
             NineUnknown_AddRef(NineUnknown(This->device));
-        /* This shouldn't be necessary:
-        if (This->container)
-            NineUnknown_Bind(NineUnknown(This->container)); */
     }
     return r;
 }
@@ -128,11 +140,34 @@ NineUnknown_Release( struct NineUnknown *This )
             if (NineUnknown_Release(NineUnknown(This->device)) == 0)
                 return r; /* everything's gone */
         }
-        if (This->container) {
-            /* NineUnknown_Unbind(NineUnknown(This->container)); */
-        } else
-        if (This->bind == 0) {
+        /* Containers (here with !forward) take care of item destruction */
+        if (!This->container && This->bind == 0) {
+            This->dtor(This);
+        }
+    }
+    return r;
+}
+
+/* No need to lock the mutex protecting nine (when D3DCREATE_MULTITHREADED)
+ * for AddRef and Release, except for dtor as some of the dtors require it. */
+ULONG NINE_WINAPI
+NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This )
+{
+    if (This->forward)
+        return NineUnknown_ReleaseWithDtorLock(This->container);
+
+    ULONG r = p_atomic_dec_return(&This->refs);
+
+    if (r == 0) {
+        if (This->device) {
+            if (NineUnknown_ReleaseWithDtorLock(NineUnknown(This->device)) == 0)
+                return r; /* everything's gone */
+        }
+        /* Containers (here with !forward) take care of item destruction */
+        if (!This->container && This->bind == 0) {
+            NineLockGlobalMutex();
             This->dtor(This);
+            NineUnlockGlobalMutex();
         }
     }
     return r;
@@ -159,15 +194,18 @@ NineUnknown_SetPrivateData( struct NineUnknown *This,
     struct pheader *header;
     const void *user_data = pData;
     char guid_str[64];
+    void *header_data;
 
     DBG("This=%p GUID=%s pData=%p SizeOfData=%u Flags=%x\n",
         This, GUID_sprintf(guid_str, refguid), pData, SizeOfData, Flags);
 
+    (void)guid_str;
+
     if (Flags & D3DSPD_IUNKNOWN)
         user_assert(SizeOfData == sizeof(IUnknown *), D3DERR_INVALIDCALL);
 
     /* data consists of a header and the actual data. avoiding 2 mallocs */
-    header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData-1);
+    header = CALLOC_VARIANT_LENGTH_STRUCT(pheader, SizeOfData);
     if (!header) { return E_OUTOFMEMORY; }
     header->unknown = (Flags & D3DSPD_IUNKNOWN) ? TRUE : FALSE;
 
@@ -182,12 +220,13 @@ NineUnknown_SetPrivateData( struct NineUnknown *This,
     }
 
     header->size = SizeOfData;
-    memcpy(header->data, user_data, header->size);
+    header_data = (void *)header + sizeof(*header);
+    memcpy(header_data, user_data, header->size);
     memcpy(&header->guid, refguid, sizeof(header->guid));
 
     err = util_hash_table_set(This->pdata, &header->guid, header);
     if (err == PIPE_OK) {
-        if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
+        if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); }
         return D3D_OK;
     }
 
@@ -206,10 +245,13 @@ NineUnknown_GetPrivateData( struct NineUnknown *This,
     struct pheader *header;
     DWORD sizeofdata;
     char guid_str[64];
+    void *header_data;
 
     DBG("This=%p GUID=%s pData=%p pSizeOfData=%p\n",
         This, GUID_sprintf(guid_str, refguid), pData, pSizeOfData);
 
+    (void)guid_str;
+
     header = util_hash_table_get(This->pdata, refguid);
     if (!header) { return D3DERR_NOTFOUND; }
 
@@ -224,8 +266,9 @@ NineUnknown_GetPrivateData( struct NineUnknown *This,
         return D3DERR_MOREDATA;
     }
 
-    if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header->data); }
-    memcpy(pData, header->data, header->size);
+    header_data = (void *)header + sizeof(*header);
+    if (header->unknown) { IUnknown_AddRef(*(IUnknown **)header_data); }
+    memcpy(pData, header_data, header->size);
 
     return D3D_OK;
 }
@@ -239,6 +282,8 @@ NineUnknown_FreePrivateData( struct NineUnknown *This,
 
     DBG("This=%p GUID=%s\n", This, GUID_sprintf(guid_str, refguid));
 
+    (void)guid_str;
+
     header = util_hash_table_get(This->pdata, refguid);
     if (!header)
         return D3DERR_NOTFOUND;