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