Home | History | Annotate | Download | only in nine
      1 /*
      2  * Copyright 2011 Joakim Sindholt <opensource (at) 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 
     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 
     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 
     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 
     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         { \
     90             HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
     91             if (FAILED(__hr)) { \
     92                 Nine##nine##_dtor(__data); \
     93                 return __hr; \
     94             } \
     95         } \
     96          \
     97         *(out) = __data; \
     98     } \
     99     return D3D_OK
    100 
    101 #define NINE_NEW(nine, out, lock, ...) \
    102     { \
    103         struct NineUnknownParams __params; \
    104         struct Nine##nine *__data; \
    105          \
    106         __data = CALLOC_STRUCT(Nine##nine); \
    107         if (!__data) { return E_OUTOFMEMORY; } \
    108          \
    109         __params.vtable = (lock) ? &Lock##nine##_vtable : &Nine##nine##_vtable; \
    110         __params.guids = Nine##nine##_IIDs; \
    111         __params.dtor = (void *)Nine##nine##_dtor; \
    112         __params.container = NULL; \
    113         __params.device = NULL; \
    114         { \
    115             HRESULT __hr = Nine##nine##_ctor(__data, &__params, ## __VA_ARGS__); \
    116             if (FAILED(__hr)) { \
    117                 Nine##nine##_dtor(__data); \
    118                 return __hr; \
    119             } \
    120         } \
    121          \
    122         *(out) = __data; \
    123     } \
    124     return D3D_OK
    125 
    126 static inline float asfloat(DWORD value)
    127 {
    128     union {
    129         float f;
    130         DWORD w;
    131     } u;
    132     u.w = value;
    133     return u.f;
    134 }
    135 
    136 struct nine_range
    137 {
    138     struct nine_range *next;
    139     int16_t bgn; /* inclusive */
    140     int16_t end; /* exclusive */
    141 };
    142 
    143 /* We won't ever need more than 256 ranges, so just allocate once. */
    144 struct nine_range_pool
    145 {
    146     struct nine_range *free;
    147     struct nine_range **slabs;
    148     unsigned num_slabs;
    149     unsigned num_slabs_max;
    150 };
    151 
    152 static inline void
    153 nine_range_pool_put(struct nine_range_pool *pool, struct nine_range *r)
    154 {
    155     r->next = pool->free;
    156     pool->free = r;
    157 }
    158 
    159 static inline void
    160 nine_range_pool_put_chain(struct nine_range_pool *pool,
    161                           struct nine_range *head,
    162                           struct nine_range *tail)
    163 {
    164     tail->next = pool->free;
    165     pool->free = head;
    166 }
    167 
    168 void
    169 nine_ranges_insert(struct nine_range **head, int16_t bgn, int16_t end,
    170                    struct nine_range_pool *pool);
    171 
    172 #endif /* _NINE_HELPERS_H_ */
    173