1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com>
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub
8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom
9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#ifndef _NINE_HELPERS_H_
24bf215546Sopenharmony_ci#define _NINE_HELPERS_H_
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "iunknown.h"
27bf215546Sopenharmony_ci#include "nine_lock.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/*
30bf215546Sopenharmony_ci * Note: we use these function rather than the MIN2, MAX2, CLAMP macros to
31bf215546Sopenharmony_ci * avoid evaluating arguments (which are often function calls) more than once.
32bf215546Sopenharmony_ci */
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistatic inline unsigned _min(unsigned a, unsigned b)
35bf215546Sopenharmony_ci{
36bf215546Sopenharmony_ci   return (a < b) ? a : b;
37bf215546Sopenharmony_ci}
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci/* Sshhh ... */
41bf215546Sopenharmony_ci#define nine_reference(a, b) _nine_reference((void **)(a), (b))
42bf215546Sopenharmony_ci
43bf215546Sopenharmony_cistatic inline void _nine_reference(void **ref, void *ptr)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci    if (*ref != ptr) {
46bf215546Sopenharmony_ci        if (*ref)
47bf215546Sopenharmony_ci            NineUnknown_Release(*ref);
48bf215546Sopenharmony_ci        if (ptr)
49bf215546Sopenharmony_ci            NineUnknown_AddRef(ptr);
50bf215546Sopenharmony_ci        *ref = ptr;
51bf215546Sopenharmony_ci    }
52bf215546Sopenharmony_ci}
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci#define nine_reference_set(a, b) _nine_reference_set((void **)(a), (b))
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistatic inline void _nine_reference_set(void **ref, void *ptr)
57bf215546Sopenharmony_ci{
58bf215546Sopenharmony_ci    *ref = ptr;
59bf215546Sopenharmony_ci    if (ptr)
60bf215546Sopenharmony_ci        NineUnknown_AddRef(ptr);
61bf215546Sopenharmony_ci}
62bf215546Sopenharmony_ci
63bf215546Sopenharmony_ci#define nine_bind(a, b) _nine_bind((void **)(a), (b))
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_cistatic inline void _nine_bind(void **dst, void *obj)
66bf215546Sopenharmony_ci{
67bf215546Sopenharmony_ci    if (*dst != obj) {
68bf215546Sopenharmony_ci        if (*dst)
69bf215546Sopenharmony_ci            NineUnknown_Unbind(*dst);
70bf215546Sopenharmony_ci        if (obj)
71bf215546Sopenharmony_ci            NineUnknown_Bind(obj);
72bf215546Sopenharmony_ci        *dst = obj;
73bf215546Sopenharmony_ci    }
74bf215546Sopenharmony_ci}
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci#define NINE_DEVICE_CHILD_NEW(nine, out, dev, ...) \
77bf215546Sopenharmony_ci    { \
78bf215546Sopenharmony_ci        struct NineUnknownParams __params; \
79bf215546Sopenharmony_ci        struct Nine##nine *__data; \
80bf215546Sopenharmony_ci         \
81bf215546Sopenharmony_ci        __data = CALLOC_STRUCT(Nine##nine); \
82bf215546Sopenharmony_ci        if (!__data) { return E_OUTOFMEMORY; } \
83bf215546Sopenharmony_ci         \
84bf215546Sopenharmony_ci        __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
85bf215546Sopenharmony_ci        __params.guids = Nine##nine##_IIDs; \
86bf215546Sopenharmony_ci        __params.dtor = (void *)Nine##nine##_dtor; \
87bf215546Sopenharmony_ci        __params.container = NULL; \
88bf215546Sopenharmony_ci        __params.device = dev; \
89bf215546Sopenharmony_ci        __params.start_with_bind_not_ref = false; \
90bf215546Sopenharmony_ci        { \
91bf215546Sopenharmony_ci            HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
92bf215546Sopenharmony_ci            if (FAILED(__hr)) { \
93bf215546Sopenharmony_ci                Nine##nine##_dtor(__data); \
94bf215546Sopenharmony_ci                return __hr; \
95bf215546Sopenharmony_ci            } \
96bf215546Sopenharmony_ci        } \
97bf215546Sopenharmony_ci         \
98bf215546Sopenharmony_ci        *(out) = __data; \
99bf215546Sopenharmony_ci    } \
100bf215546Sopenharmony_ci    return D3D_OK
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci#define NINE_DEVICE_CHILD_BIND_NEW(nine, out, dev, ...) \
103bf215546Sopenharmony_ci    { \
104bf215546Sopenharmony_ci        struct NineUnknownParams __params; \
105bf215546Sopenharmony_ci        struct Nine##nine *__data; \
106bf215546Sopenharmony_ci         \
107bf215546Sopenharmony_ci        __data = CALLOC_STRUCT(Nine##nine); \
108bf215546Sopenharmony_ci        if (!__data) { return E_OUTOFMEMORY; } \
109bf215546Sopenharmony_ci         \
110bf215546Sopenharmony_ci        __params.vtable = ((dev)->params.BehaviorFlags & D3DCREATE_MULTITHREADED) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
111bf215546Sopenharmony_ci        __params.guids = Nine##nine##_IIDs; \
112bf215546Sopenharmony_ci        __params.dtor = (void *)Nine##nine##_dtor; \
113bf215546Sopenharmony_ci        __params.container = NULL; \
114bf215546Sopenharmony_ci        __params.device = dev; \
115bf215546Sopenharmony_ci        __params.start_with_bind_not_ref = true; \
116bf215546Sopenharmony_ci        { \
117bf215546Sopenharmony_ci            HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
118bf215546Sopenharmony_ci            if (FAILED(__hr)) { \
119bf215546Sopenharmony_ci                Nine##nine##_dtor(__data); \
120bf215546Sopenharmony_ci                return __hr; \
121bf215546Sopenharmony_ci            } \
122bf215546Sopenharmony_ci        } \
123bf215546Sopenharmony_ci         \
124bf215546Sopenharmony_ci        *(out) = __data; \
125bf215546Sopenharmony_ci    } \
126bf215546Sopenharmony_ci    return D3D_OK
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci#define NINE_NEW(nine, out, lock, ...) \
129bf215546Sopenharmony_ci    { \
130bf215546Sopenharmony_ci        struct NineUnknownParams __params; \
131bf215546Sopenharmony_ci        struct Nine##nine *__data; \
132bf215546Sopenharmony_ci         \
133bf215546Sopenharmony_ci        __data = CALLOC_STRUCT(Nine##nine); \
134bf215546Sopenharmony_ci        if (!__data) { return E_OUTOFMEMORY; } \
135bf215546Sopenharmony_ci         \
136bf215546Sopenharmony_ci        __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
137bf215546Sopenharmony_ci        __params.guids = Nine##nine##_IIDs; \
138bf215546Sopenharmony_ci        __params.dtor = (void *)Nine##nine##_dtor; \
139bf215546Sopenharmony_ci        __params.container = NULL; \
140bf215546Sopenharmony_ci        __params.device = NULL; \
141bf215546Sopenharmony_ci        __params.start_with_bind_not_ref = false; \
142bf215546Sopenharmony_ci        { \
143bf215546Sopenharmony_ci            HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
144bf215546Sopenharmony_ci            if (FAILED(__hr)) { \
145bf215546Sopenharmony_ci                Nine##nine##_dtor(__data); \
146bf215546Sopenharmony_ci                return __hr; \
147bf215546Sopenharmony_ci            } \
148bf215546Sopenharmony_ci        } \
149bf215546Sopenharmony_ci         \
150bf215546Sopenharmony_ci        *(out) = __data; \
151bf215546Sopenharmony_ci    } \
152bf215546Sopenharmony_ci    return D3D_OK
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_cistatic inline float asfloat(DWORD value)
155bf215546Sopenharmony_ci{
156bf215546Sopenharmony_ci    union {
157bf215546Sopenharmony_ci        float f;
158bf215546Sopenharmony_ci        DWORD w;
159bf215546Sopenharmony_ci    } u;
160bf215546Sopenharmony_ci    u.w = value;
161bf215546Sopenharmony_ci    return u.f;
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_cistruct nine_range
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci    struct nine_range *next;
167bf215546Sopenharmony_ci    int16_t bgn; /* inclusive */
168bf215546Sopenharmony_ci    int16_t end; /* exclusive */
169bf215546Sopenharmony_ci};
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci/* We won't ever need more than 256 ranges, so just allocate once. */
172bf215546Sopenharmony_cistruct nine_range_pool
173bf215546Sopenharmony_ci{
174bf215546Sopenharmony_ci    struct nine_range *free;
175bf215546Sopenharmony_ci    struct nine_range **slabs;
176bf215546Sopenharmony_ci    unsigned num_slabs;
177bf215546Sopenharmony_ci    unsigned num_slabs_max;
178bf215546Sopenharmony_ci};
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_cistatic inline void
181bf215546Sopenharmony_cinine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r)
182bf215546Sopenharmony_ci{
183bf215546Sopenharmony_ci    r->next = pool->free;
184bf215546Sopenharmony_ci    pool->free = r;
185bf215546Sopenharmony_ci}
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_cistatic inline void
188bf215546Sopenharmony_cinine_range_pool_put_chain(struct nine_range_pool *pool,
189bf215546Sopenharmony_ci                          struct nine_range *head,
190bf215546Sopenharmony_ci                          struct nine_range *tail)
191bf215546Sopenharmony_ci{
192bf215546Sopenharmony_ci    tail->next = pool->free;
193bf215546Sopenharmony_ci    pool->free = head;
194bf215546Sopenharmony_ci}
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_civoid
197bf215546Sopenharmony_cinine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end,
198bf215546Sopenharmony_ci                   struct nine_range_pool *pool);
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci#endif /* _NINE_HELPERS_H_ */
201