st/va: Check NULL pointer
[mesa.git] / src / gallium / state_trackers / nine / iunknown.h
1 /*
2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22
23 #ifndef _NINE_IUNKNOWN_H_
24 #define _NINE_IUNKNOWN_H_
25
26 #include "pipe/p_compiler.h"
27
28 #include "util/u_memory.h"
29
30 #include "guid.h"
31 #include "nine_flags.h"
32 #include "nine_debug.h"
33 #include "nine_quirk.h"
34
35 #include "d3d9.h"
36
37 struct Nine9;
38 struct NineDevice9;
39
40 struct NineUnknown
41 {
42 /* pointer to vtable (can be overriden outside gallium nine) */
43 void *vtable;
44 /* pointer to internal vtable */
45 void *vtable_internal;
46
47 int32_t refs; /* external reference count */
48 int32_t bind; /* internal bind count */
49 boolean forward; /* whether to forward references to the container */
50
51 struct NineUnknown *container; /* referenced if (refs | bind) */
52 struct NineDevice9 *device; /* referenced if (refs) */
53
54 const GUID **guids; /* for QueryInterface */
55
56 void (*dtor)(void *data); /* top-level dtor */
57 };
58 static inline struct NineUnknown *
59 NineUnknown( void *data )
60 {
61 return (struct NineUnknown *)data;
62 }
63
64 /* Use this instead of a shitload of arguments: */
65 struct NineUnknownParams
66 {
67 void *vtable;
68 const GUID **guids;
69 void (*dtor)(void *data);
70 struct NineUnknown *container;
71 struct NineDevice9 *device;
72 };
73
74 HRESULT
75 NineUnknown_ctor( struct NineUnknown *This,
76 struct NineUnknownParams *pParams );
77
78 void
79 NineUnknown_dtor( struct NineUnknown *This );
80
81 /*** Direct3D public methods ***/
82
83 HRESULT NINE_WINAPI
84 NineUnknown_QueryInterface( struct NineUnknown *This,
85 REFIID riid,
86 void **ppvObject );
87
88 ULONG NINE_WINAPI
89 NineUnknown_AddRef( struct NineUnknown *This );
90
91 ULONG NINE_WINAPI
92 NineUnknown_Release( struct NineUnknown *This );
93
94 HRESULT NINE_WINAPI
95 NineUnknown_GetDevice( struct NineUnknown *This,
96 IDirect3DDevice9 **ppDevice );
97
98 /*** Nine private methods ***/
99
100 static inline void
101 NineUnknown_Destroy( struct NineUnknown *This )
102 {
103 assert(!(This->refs | This->bind));
104 This->dtor(This);
105 }
106
107 static inline UINT
108 NineUnknown_Bind( struct NineUnknown *This )
109 {
110 UINT b = ++This->bind;
111 assert(b);
112 if (b == 1 && This->container) {
113 if (This->container != NineUnknown(This->device))
114 NineUnknown_Bind(This->container);
115 }
116 return b;
117 }
118
119 static inline UINT
120 NineUnknown_Unbind( struct NineUnknown *This )
121 {
122 UINT b = --This->bind;
123 if (!b) {
124 if (This->container) {
125 if (This->container != NineUnknown(This->device))
126 NineUnknown_Unbind(This->container);
127 } else
128 if (This->refs == 0) {
129 This->dtor(This);
130 }
131 }
132 return b;
133 }
134
135 static inline void
136 NineUnknown_ConvertRefToBind( struct NineUnknown *This )
137 {
138 NineUnknown_Bind(This);
139 NineUnknown_Release(This);
140 }
141
142 /* Detach from container. */
143 static inline void
144 NineUnknown_Detach( struct NineUnknown *This )
145 {
146 assert(This->container && !This->forward);
147 if (This->refs)
148 NineUnknown_Unbind(This->container);
149 if (This->bind)
150 NineUnknown_Unbind(This->container);
151 This->container = NULL;
152 if (!(This->refs | This->bind))
153 This->dtor(This);
154 }
155
156 #endif /* _NINE_IUNKNOWN_H_ */