1 /*
2 * Copyright 2011 Joakim Sindholt <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef _NINE_IUNKNOWN_H_
7 #define _NINE_IUNKNOWN_H_
8
9 #include "util/compiler.h"
10
11 #include "util/u_atomic.h"
12 #include "util/u_memory.h"
13
14 #include "guid.h"
15 #include "nine_flags.h"
16 #include "nine_debug.h"
17 #include "nine_quirk.h"
18
19 #include "d3d9.h"
20
21 struct Nine9;
22 struct NineDevice9;
23
24 struct NineUnknown
25 {
26 /* pointer to vtable (can be overridden outside gallium nine) */
27 void *vtable;
28 /* pointer to internal vtable */
29 void *vtable_internal;
30
31 int32_t refs; /* external reference count */
32 int32_t bind; /* internal bind count */
33 int32_t has_bind_or_refs; /* 0 if no ref, 1 if bind or ref, 2 if both */
34 bool forward; /* whether to forward references to the container */
35
36 /* container: for surfaces and volumes only.
37 * Can be a texture, a volume texture or a swapchain.
38 * forward is set to false for the swapchain case.
39 * If forward is set, refs are passed to the container if forward is set
40 * and the container has bind increased if the object has non null bind. */
41 struct NineUnknown *container;
42 struct NineDevice9 *device; /* referenced if (refs) */
43
44 const GUID **guids; /* for QueryInterface */
45
46 /* for [GS]etPrivateData/FreePrivateData */
47 struct hash_table *pdata;
48
49 void (*dtor)(void *data); /* top-level dtor */
50 };
51 static inline struct NineUnknown *
NineUnknown(void * data)52 NineUnknown( void *data )
53 {
54 return (struct NineUnknown *)data;
55 }
56
57 /* Use this instead of a shitload of arguments: */
58 struct NineUnknownParams
59 {
60 void *vtable;
61 const GUID **guids;
62 void (*dtor)(void *data);
63 struct NineUnknown *container;
64 struct NineDevice9 *device;
65 bool start_with_bind_not_ref;
66 };
67
68 HRESULT
69 NineUnknown_ctor( struct NineUnknown *This,
70 struct NineUnknownParams *pParams );
71
72 void
73 NineUnknown_dtor( struct NineUnknown *This );
74
75 /*** Direct3D public methods ***/
76
77 HRESULT NINE_WINAPI
78 NineUnknown_QueryInterface( struct NineUnknown *This,
79 REFIID riid,
80 void **ppvObject );
81
82 ULONG NINE_WINAPI
83 NineUnknown_AddRef( struct NineUnknown *This );
84
85 ULONG NINE_WINAPI
86 NineUnknown_Release( struct NineUnknown *This );
87
88 ULONG NINE_WINAPI
89 NineUnknown_ReleaseWithDtorLock( struct NineUnknown *This );
90
91 HRESULT NINE_WINAPI
92 NineUnknown_GetDevice( struct NineUnknown *This,
93 IDirect3DDevice9 **ppDevice );
94
95 HRESULT NINE_WINAPI
96 NineUnknown_SetPrivateData( struct NineUnknown *This,
97 REFGUID refguid,
98 const void *pData,
99 DWORD SizeOfData,
100 DWORD Flags );
101
102 HRESULT NINE_WINAPI
103 NineUnknown_GetPrivateData( struct NineUnknown *This,
104 REFGUID refguid,
105 void *pData,
106 DWORD *pSizeOfData );
107
108 HRESULT NINE_WINAPI
109 NineUnknown_FreePrivateData( struct NineUnknown *This,
110 REFGUID refguid );
111
112 /*** Nine private methods ***/
113
114 static inline void
NineUnknown_Destroy(struct NineUnknown * This)115 NineUnknown_Destroy( struct NineUnknown *This )
116 {
117 assert(!(This->refs | This->bind) && !This->has_bind_or_refs);
118 This->dtor(This);
119 }
120
121 static inline UINT
NineUnknown_Bind(struct NineUnknown * This)122 NineUnknown_Bind( struct NineUnknown *This )
123 {
124 UINT b = p_atomic_inc_return(&This->bind);
125 assert(b);
126
127 if (b == 1)
128 p_atomic_inc(&This->has_bind_or_refs);
129 if (b == 1 && This->forward)
130 NineUnknown_Bind(This->container);
131
132 return b;
133 }
134
135 static inline UINT
NineUnknown_Unbind(struct NineUnknown * This)136 NineUnknown_Unbind( struct NineUnknown *This )
137 {
138 UINT b = p_atomic_dec_return(&This->bind);
139 UINT b_or_ref = 1;
140
141 if (b == 0)
142 b_or_ref = p_atomic_dec_return(&This->has_bind_or_refs);
143 if (b == 0 && This->forward)
144 NineUnknown_Unbind(This->container);
145 else if (b_or_ref == 0 && !This->container)
146 This->dtor(This);
147
148 return b;
149 }
150
151 static inline void
NineUnknown_ConvertRefToBind(struct NineUnknown * This)152 NineUnknown_ConvertRefToBind( struct NineUnknown *This )
153 {
154 NineUnknown_Bind(This);
155 NineUnknown_Release(This);
156 }
157
158 /* Detach from container. */
159 static inline void
NineUnknown_Detach(struct NineUnknown * This)160 NineUnknown_Detach( struct NineUnknown *This )
161 {
162 assert(This->container && !This->forward);
163
164 This->container = NULL;
165 if (!(This->has_bind_or_refs))
166 This->dtor(This);
167 }
168
169 #endif /* _NINE_IUNKNOWN_H_ */
170