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
34static 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
43static 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
56static 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
65static 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
154static 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
164struct 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. */
172struct 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
180static inline void
181nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r)
182{
183    r->next = pool->free;
184    pool->free = r;
185}
186
187static inline void
188nine_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
196void
197nine_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