xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/nine/iunknown.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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