1 /*
2 * Copyright 2011 Joakim Sindholt <[email protected]>
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef _NINE_HELPERS_H_
7 #define _NINE_HELPERS_H_
8
9 #include "iunknown.h"
10 #include "nine_lock.h"
11
12 /*
13 * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to
14 * avoid evaluating arguments (which are often function calls) more than once.
15 */
16
_min(unsigned a,unsigned b)17 static inline unsigned _min(unsigned a, unsigned b)
18 {
19 return (a < b) ? a : b;
20 }
21
22
23 /* Sshhh ... */
24 #define nine_reference(a, b) _nine_reference((void **)(a), (b))
25
_nine_reference(void ** ref,void * ptr)26 static inline void _nine_reference(void **ref, void *ptr)
27 {
28 if (*ref != ptr) {
29 if (*ref)
30 NineUnknown_Release(*ref);
31 if (ptr)
32 NineUnknown_AddRef(ptr);
33 *ref = ptr;
34 }
35 }
36
37 #define nine_reference_set(a, b) _nine_reference_set((void **)(a), (b))
38
_nine_reference_set(void ** ref,void * ptr)39 static inline void _nine_reference_set(void **ref, void *ptr)
40 {
41 *ref = ptr;
42 if (ptr)
43 NineUnknown_AddRef(ptr);
44 }
45
46 #define nine_bind(a, b) _nine_bind((void **)(a), (b))
47
_nine_bind(void ** dst,void * obj)48 static inline void _nine_bind(void **dst, void *obj)
49 {
50 if (*dst != obj) {
51 if (*dst)
52 NineUnknown_Unbind(*dst);
53 if (obj)
54 NineUnknown_Bind(obj);
55 *dst = obj;
56 }
57 }
58
59 #define NINE_DEVICE_CHILD_NEW(nine, out, dev, ...) \
60 { \
61 struct NineUnknownParams __params; \
62 struct Nine##nine *__data; \
63 \
64 __data = CALLOC_STRUCT(Nine##nine); \
65 if (!__data) { return E_OUTOFMEMORY; } \
66 \
67 __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
68 __params.guids = Nine##nine##_IIDs; \
69 __params.dtor = (void *)Nine##nine##_dtor; \
70 __params.container = NULL; \
71 __params.device = dev; \
72 __params.start_with_bind_not_ref = false; \
73 { \
74 HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
75 if (FAILED(__hr)) { \
76 Nine##nine##_dtor(__data); \
77 return __hr; \
78 } \
79 } \
80 \
81 *(out) = __data; \
82 } \
83 return D3D_OK
84
85 #define NINE_DEVICE_CHILD_BIND_NEW(nine, out, dev, ...) \
86 { \
87 struct NineUnknownParams __params; \
88 struct Nine##nine *__data; \
89 \
90 __data = CALLOC_STRUCT(Nine##nine); \
91 if (!__data) { return E_OUTOFMEMORY; } \
92 \
93 __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
94 __params.guids = Nine##nine##_IIDs; \
95 __params.dtor = (void *)Nine##nine##_dtor; \
96 __params.container = NULL; \
97 __params.device = dev; \
98 __params.start_with_bind_not_ref = true; \
99 { \
100 HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
101 if (FAILED(__hr)) { \
102 Nine##nine##_dtor(__data); \
103 return __hr; \
104 } \
105 } \
106 \
107 *(out) = __data; \
108 } \
109 return D3D_OK
110
111 #define NINE_NEW(nine, out, lock, ...) \
112 { \
113 struct NineUnknownParams __params; \
114 struct Nine##nine *__data; \
115 \
116 __data = CALLOC_STRUCT(Nine##nine); \
117 if (!__data) { return E_OUTOFMEMORY; } \
118 \
119 __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
120 __params.guids = Nine##nine##_IIDs; \
121 __params.dtor = (void *)Nine##nine##_dtor; \
122 __params.container = NULL; \
123 __params.device = NULL; \
124 __params.start_with_bind_not_ref = false; \
125 { \
126 HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
127 if (FAILED(__hr)) { \
128 Nine##nine##_dtor(__data); \
129 return __hr; \
130 } \
131 } \
132 \
133 *(out) = __data; \
134 } \
135 return D3D_OK
136
asfloat(DWORD value)137 static inline float asfloat(DWORD value)
138 {
139 union {
140 float f;
141 DWORD w;
142 } u;
143 u.w = value;
144 return u.f;
145 }
146
147 struct nine_range
148 {
149 struct nine_range *next;
150 int16_t bgn; /* inclusive */
151 int16_t end; /* exclusive */
152 };
153
154 /* We won't ever need more than 256 ranges, so just allocate once. */
155 struct nine_range_pool
156 {
157 struct nine_range *free;
158 struct nine_range **slabs;
159 unsigned num_slabs;
160 unsigned num_slabs_max;
161 };
162
163 static inline void
nine_range_pool_put(struct nine_range_pool * pool,struct nine_range * r)164 nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r)
165 {
166 r->next = pool->free;
167 pool->free = r;
168 }
169
170 static inline void
nine_range_pool_put_chain(struct nine_range_pool * pool,struct nine_range * head,struct nine_range * tail)171 nine_range_pool_put_chain(struct nine_range_pool *pool,
172 struct nine_range *head,
173 struct nine_range *tail)
174 {
175 tail->next = pool->free;
176 pool->free = head;
177 }
178
179 void
180 nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end,
181 struct nine_range_pool *pool);
182
183 #endif /* _NINE_HELPERS_H_ */
184