Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/vkd3d/include/private/vkd3d_common.h
4393 views
1
/*
2
* Copyright 2016 Józef Kucia for CodeWeavers
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#ifndef __VKD3D_COMMON_H
20
#define __VKD3D_COMMON_H
21
22
#include "config.h"
23
#define WIN32_LEAN_AND_MEAN
24
#include "windows.h"
25
#include "vkd3d_types.h"
26
27
#include <ctype.h>
28
#include <limits.h>
29
#include <stdbool.h>
30
#include <stdint.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#ifndef _WIN32
34
#include <pthread.h>
35
#endif
36
37
#ifdef _MSC_VER
38
#include <intrin.h>
39
#endif
40
41
#ifndef ARRAY_SIZE
42
# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
43
#endif
44
45
#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)
46
47
#define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])
48
49
#define VKD3D_ASSERT(cond) \
50
do { \
51
if (!(cond)) \
52
ERR("Failed assertion: %s\n", #cond); \
53
} while (0)
54
55
#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)
56
57
#define VKD3D_MAKE_TAG(ch0, ch1, ch2, ch3) \
58
((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) \
59
| ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24))
60
61
#define VKD3D_EXPAND(x) x
62
#define VKD3D_STRINGIFY(x) #x
63
#define VKD3D_EXPAND_AND_STRINGIFY(x) VKD3D_EXPAND(VKD3D_STRINGIFY(x))
64
65
#define vkd3d_clamp(value, lower, upper) max(min(value, upper), lower)
66
67
#define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9')
68
#define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4')
69
#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T')
70
#define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B')
71
#define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C')
72
#define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L')
73
#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0')
74
#define TAG_FXLC VKD3D_MAKE_TAG('F', 'X', 'L', 'C')
75
#define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1')
76
#define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N')
77
#define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1')
78
#define TAG_OSG5 VKD3D_MAKE_TAG('O', 'S', 'G', '5')
79
#define TAG_OSGN VKD3D_MAKE_TAG('O', 'S', 'G', 'N')
80
#define TAG_PCSG VKD3D_MAKE_TAG('P', 'C', 'S', 'G')
81
#define TAG_PSG1 VKD3D_MAKE_TAG('P', 'S', 'G', '1')
82
#define TAG_RD11 VKD3D_MAKE_TAG('R', 'D', '1', '1')
83
#define TAG_RDEF VKD3D_MAKE_TAG('R', 'D', 'E', 'F')
84
#define TAG_RTS0 VKD3D_MAKE_TAG('R', 'T', 'S', '0')
85
#define TAG_SDBG VKD3D_MAKE_TAG('S', 'D', 'B', 'G')
86
#define TAG_SFI0 VKD3D_MAKE_TAG('S', 'F', 'I', '0')
87
#define TAG_SHDR VKD3D_MAKE_TAG('S', 'H', 'D', 'R')
88
#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')
89
#define TAG_STAT VKD3D_MAKE_TAG('S', 'T', 'A', 'T')
90
#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')
91
#define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P')
92
#define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S')
93
94
#define TAG_RD11_REVERSE 0x25441313
95
96
static inline uint64_t align(uint64_t addr, size_t alignment)
97
{
98
return (addr + (alignment - 1)) & ~(alignment - 1);
99
}
100
101
#if defined(__GNUC__) || defined(__clang__)
102
# define VKD3D_NORETURN __attribute__((noreturn))
103
# ifdef __MINGW_PRINTF_FORMAT
104
# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))
105
# else
106
# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))
107
# endif
108
# define VKD3D_UNUSED __attribute__((unused))
109
# define VKD3D_UNREACHABLE __builtin_unreachable()
110
#else
111
# define VKD3D_NORETURN
112
# define VKD3D_PRINTF_FUNC(fmt, args)
113
# define VKD3D_UNUSED
114
# define VKD3D_UNREACHABLE (void)0
115
#endif /* __GNUC__ */
116
117
#define vkd3d_unreachable() \
118
do { \
119
ERR("%s:%u: Unreachable code reached.\n", __FILE__, __LINE__); \
120
VKD3D_UNREACHABLE; \
121
} while (0)
122
123
#ifdef VKD3D_NO_TRACE_MESSAGES
124
#define TRACE(args...) do { } while (0)
125
#define TRACE_ON() (false)
126
#endif
127
128
#ifdef VKD3D_NO_DEBUG_MESSAGES
129
#define WARN(args...) do { } while (0)
130
#define FIXME(args...) do { } while (0)
131
#define WARN_ON() (false)
132
#define FIXME_ONCE(args...) do { } while (0)
133
#endif
134
135
#ifdef VKD3D_NO_ERROR_MESSAGES
136
#define ERR(args...) do { } while (0)
137
#define MESSAGE(args...) do { } while (0)
138
#endif
139
140
enum vkd3d_dbg_level
141
{
142
VKD3D_DBG_LEVEL_NONE,
143
VKD3D_DBG_LEVEL_MESSAGE,
144
VKD3D_DBG_LEVEL_ERR,
145
VKD3D_DBG_LEVEL_FIXME,
146
VKD3D_DBG_LEVEL_WARN,
147
VKD3D_DBG_LEVEL_TRACE,
148
};
149
150
enum vkd3d_dbg_level vkd3d_dbg_get_level(void);
151
152
void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4);
153
void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback);
154
155
const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2);
156
const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args);
157
const char *debugstr_a(const char *str);
158
const char *debugstr_an(const char *str, size_t n);
159
const char *debugstr_w(const WCHAR *wstr, size_t wchar_size);
160
161
#define VKD3D_DBG_LOG(level) \
162
do { \
163
const enum vkd3d_dbg_level vkd3d_dbg_level = VKD3D_DBG_LEVEL_##level; \
164
VKD3D_DBG_PRINTF_##level
165
166
#define VKD3D_DBG_LOG_ONCE(first_time_level, level) \
167
do { \
168
static bool vkd3d_dbg_next_time; \
169
const enum vkd3d_dbg_level vkd3d_dbg_level = vkd3d_dbg_next_time \
170
? VKD3D_DBG_LEVEL_##level : VKD3D_DBG_LEVEL_##first_time_level; \
171
vkd3d_dbg_next_time = true; \
172
VKD3D_DBG_PRINTF_##level
173
174
#define VKD3D_DBG_PRINTF(...) \
175
vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)
176
177
#define VKD3D_DBG_PRINTF_TRACE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)
178
#define VKD3D_DBG_PRINTF_WARN(...) VKD3D_DBG_PRINTF(__VA_ARGS__)
179
#define VKD3D_DBG_PRINTF_FIXME(...) VKD3D_DBG_PRINTF(__VA_ARGS__)
180
#define VKD3D_DBG_PRINTF_MESSAGE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)
181
182
#ifdef VKD3D_ABORT_ON_ERR
183
#define VKD3D_DBG_PRINTF_ERR(...) \
184
vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); \
185
abort(); \
186
} while (0)
187
#else
188
#define VKD3D_DBG_PRINTF_ERR(...) VKD3D_DBG_PRINTF(__VA_ARGS__)
189
#endif
190
191
/* Used by vkd3d_unreachable(). */
192
#ifdef VKD3D_CROSSTEST
193
#undef ERR
194
#define ERR(...) do { fprintf(stderr, __VA_ARGS__); abort(); } while (0)
195
#endif
196
197
#ifndef TRACE
198
#define TRACE VKD3D_DBG_LOG(TRACE)
199
#endif
200
201
#ifndef WARN
202
#define WARN VKD3D_DBG_LOG(WARN)
203
#endif
204
205
#ifndef FIXME
206
#define FIXME VKD3D_DBG_LOG(FIXME)
207
#endif
208
209
#ifndef ERR
210
#define ERR VKD3D_DBG_LOG(ERR)
211
#endif
212
213
#ifndef MESSAGE
214
#define MESSAGE VKD3D_DBG_LOG(MESSAGE)
215
#endif
216
217
#ifndef TRACE_ON
218
#define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE)
219
#endif
220
221
#ifndef WARN_ON
222
#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN)
223
#endif
224
225
#ifndef FIXME_ONCE
226
#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)
227
#endif
228
229
#define VKD3D_DEBUG_ENV_NAME(name) const char *const vkd3d_dbg_env_name = name
230
231
static inline const char *debugstr_guid(const GUID *guid)
232
{
233
if (!guid)
234
return "(null)";
235
236
return vkd3d_dbg_sprintf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
237
(unsigned long)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
238
guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
239
guid->Data4[5], guid->Data4[6], guid->Data4[7]);
240
}
241
242
static inline const char *debugstr_hresult(HRESULT hr)
243
{
244
switch (hr)
245
{
246
#define TO_STR(u) case u: return #u;
247
TO_STR(S_OK)
248
TO_STR(S_FALSE)
249
TO_STR(E_NOTIMPL)
250
TO_STR(E_NOINTERFACE)
251
TO_STR(E_POINTER)
252
TO_STR(E_ABORT)
253
TO_STR(E_FAIL)
254
TO_STR(E_OUTOFMEMORY)
255
TO_STR(E_INVALIDARG)
256
TO_STR(DXGI_ERROR_NOT_FOUND)
257
TO_STR(DXGI_ERROR_MORE_DATA)
258
TO_STR(DXGI_ERROR_UNSUPPORTED)
259
#undef TO_STR
260
default:
261
return vkd3d_dbg_sprintf("%#x", (int)hr);
262
}
263
}
264
265
unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value);
266
267
struct vkd3d_debug_option
268
{
269
const char *name;
270
uint64_t flag;
271
};
272
273
bool vkd3d_debug_list_has_member(const char *string, const char *member);
274
uint64_t vkd3d_parse_debug_options(const char *string,
275
const struct vkd3d_debug_option *options, unsigned int option_count);
276
void vkd3d_set_thread_name(const char *name);
277
278
static inline unsigned int vkd3d_popcount(unsigned int v)
279
{
280
#ifdef _MSC_VER
281
return __popcnt(v);
282
#elif defined(__MINGW32__)
283
return __builtin_popcount(v);
284
#else
285
v -= (v >> 1) & 0x55555555;
286
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
287
return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
288
#endif
289
}
290
291
static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask)
292
{
293
unsigned int i, j;
294
295
for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i)
296
{
297
if (mask & (1u << i))
298
++j;
299
else if (j)
300
break;
301
}
302
303
return vkd3d_popcount(mask) == j;
304
}
305
306
/* Undefined for x == 0. */
307
static inline unsigned int vkd3d_log2i(unsigned int x)
308
{
309
#ifdef _WIN32
310
/* _BitScanReverse returns the index of the highest set bit,
311
* unlike clz which is 31 - index. */
312
ULONG result;
313
_BitScanReverse(&result, x);
314
return (unsigned int)result;
315
#elif defined(HAVE_BUILTIN_CLZ)
316
return __builtin_clz(x) ^ 0x1f;
317
#else
318
static const unsigned int l[] =
319
{
320
~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
321
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
322
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
323
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
324
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
325
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
326
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
327
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
328
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
329
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
330
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
331
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
332
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
333
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
334
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
335
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
336
};
337
unsigned int i;
338
339
return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24
340
: l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
341
#endif
342
}
343
344
static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
345
{
346
const char *str = haystack;
347
348
while (haystack_len >= needle_len)
349
{
350
if (!memcmp(str, needle, needle_len))
351
return (char *)str;
352
++str;
353
--haystack_len;
354
}
355
return NULL;
356
}
357
358
static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit)
359
{
360
#ifdef HAVE_BUILTIN_ADD_OVERFLOW
361
size_t sum;
362
363
return !__builtin_add_overflow(start, count, &sum) && sum <= limit;
364
#else
365
return start <= limit && count <= limit - start;
366
#endif
367
}
368
369
static inline bool vkd3d_object_range_overflow(size_t start, size_t count, size_t size)
370
{
371
return (~(size_t)0 - start) / size < count;
372
}
373
374
static inline uint16_t vkd3d_make_u16(uint8_t low, uint8_t high)
375
{
376
return low | ((uint16_t)high << 8);
377
}
378
379
static inline uint32_t vkd3d_make_u32(uint16_t low, uint16_t high)
380
{
381
return low | ((uint32_t)high << 16);
382
}
383
384
static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)
385
{
386
return (x > y) - (x < y);
387
}
388
389
static inline int vkd3d_u64_compare(uint64_t x, uint64_t y)
390
{
391
return (x > y) - (x < y);
392
}
393
394
#define VKD3D_BITMAP_SIZE(x) (((x) + 0x1f) >> 5)
395
396
static inline bool bitmap_clear(uint32_t *map, unsigned int idx)
397
{
398
return map[idx >> 5] &= ~(1u << (idx & 0x1f));
399
}
400
401
static inline bool bitmap_set(uint32_t *map, unsigned int idx)
402
{
403
return map[idx >> 5] |= (1u << (idx & 0x1f));
404
}
405
406
static inline bool bitmap_is_set(const uint32_t *map, unsigned int idx)
407
{
408
return map[idx >> 5] & (1u << (idx & 0x1f));
409
}
410
411
static inline int ascii_isupper(int c)
412
{
413
return 'A' <= c && c <= 'Z';
414
}
415
416
static inline int ascii_tolower(int c)
417
{
418
return ascii_isupper(c) ? c - 'A' + 'a' : c;
419
}
420
421
static inline int ascii_strncasecmp(const char *a, const char *b, size_t n)
422
{
423
int c_a, c_b;
424
425
while (n--)
426
{
427
c_a = ascii_tolower(*a++);
428
c_b = ascii_tolower(*b++);
429
if (c_a != c_b || !c_a)
430
return c_a - c_b;
431
}
432
return 0;
433
}
434
435
static inline int ascii_strcasecmp(const char *a, const char *b)
436
{
437
int c_a, c_b;
438
439
do
440
{
441
c_a = ascii_tolower(*a++);
442
c_b = ascii_tolower(*b++);
443
} while (c_a == c_b && c_a != '\0');
444
445
return c_a - c_b;
446
}
447
448
static inline uint64_t vkd3d_atomic_add_fetch_u64(uint64_t volatile *x, uint64_t val)
449
{
450
#if HAVE_SYNC_ADD_AND_FETCH
451
return __sync_add_and_fetch(x, val);
452
#elif defined(_WIN32)
453
return InterlockedAdd64((LONG64 *)x, val);
454
#else
455
# error "vkd3d_atomic_add_fetch_u64() not implemented for this platform"
456
#endif
457
}
458
459
static inline uint32_t vkd3d_atomic_add_fetch_u32(uint32_t volatile *x, uint32_t val)
460
{
461
#if HAVE_SYNC_ADD_AND_FETCH
462
return __sync_add_and_fetch(x, val);
463
#elif defined(_WIN32)
464
return InterlockedAdd((LONG *)x, val);
465
#else
466
# error "vkd3d_atomic_add_fetch_u32() not implemented for this platform"
467
#endif
468
}
469
470
static inline uint64_t vkd3d_atomic_increment_u64(uint64_t volatile *x)
471
{
472
return vkd3d_atomic_add_fetch_u64(x, 1);
473
}
474
475
static inline uint32_t vkd3d_atomic_decrement_u32(uint32_t volatile *x)
476
{
477
return vkd3d_atomic_add_fetch_u32(x, ~0u);
478
}
479
480
static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)
481
{
482
return vkd3d_atomic_add_fetch_u32(x, 1);
483
}
484
485
static inline bool vkd3d_atomic_compare_exchange_u32(uint32_t volatile *x, uint32_t expected, uint32_t val)
486
{
487
#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
488
return __sync_bool_compare_and_swap(x, expected, val);
489
#elif defined(_WIN32)
490
return InterlockedCompareExchange((LONG *)x, val, expected) == expected;
491
#else
492
# error "vkd3d_atomic_compare_exchange_u32() not implemented for this platform"
493
#endif
494
}
495
496
static inline bool vkd3d_atomic_compare_exchange_ptr(void * volatile *x, void *expected, void *val)
497
{
498
#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP
499
return __sync_bool_compare_and_swap(x, expected, val);
500
#elif defined(_WIN32)
501
return InterlockedCompareExchangePointer(x, val, expected) == expected;
502
#else
503
# error "vkd3d_atomic_compare_exchange_ptr() not implemented for this platform"
504
#endif
505
}
506
507
static inline uint32_t vkd3d_atomic_exchange_u32(uint32_t volatile *x, uint32_t val)
508
{
509
#if HAVE_ATOMIC_EXCHANGE_N
510
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
511
#elif defined(_WIN32)
512
return InterlockedExchange((LONG *)x, val);
513
#else
514
uint32_t expected;
515
516
do
517
{
518
expected = *x;
519
} while (!vkd3d_atomic_compare_exchange_u32(x, expected, val));
520
521
return expected;
522
#endif
523
}
524
525
static inline void *vkd3d_atomic_exchange_ptr(void * volatile *x, void *val)
526
{
527
#if HAVE_ATOMIC_EXCHANGE_N
528
return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);
529
#elif defined(_WIN32)
530
return InterlockedExchangePointer(x, val);
531
#else
532
void *expected;
533
534
do
535
{
536
expected = *x;
537
} while (!vkd3d_atomic_compare_exchange_ptr(x, expected, val));
538
539
return expected;
540
#endif
541
}
542
543
struct vkd3d_mutex
544
{
545
#ifdef _WIN32
546
CRITICAL_SECTION lock;
547
#else
548
pthread_mutex_t lock;
549
#endif
550
};
551
552
#ifdef _WIN32
553
#define VKD3D_MUTEX_INITIALIZER {{NULL, -1, 0, 0, 0, 0}}
554
#else
555
#define VKD3D_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
556
#endif
557
558
static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)
559
{
560
#ifdef _WIN32
561
InitializeCriticalSection(&lock->lock);
562
#else
563
int ret;
564
565
if ((ret = pthread_mutex_init(&lock->lock, NULL)))
566
ERR("Failed to initialise the mutex, ret %d.\n", ret);
567
#endif
568
}
569
570
static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)
571
{
572
#ifdef _WIN32
573
EnterCriticalSection(&lock->lock);
574
#else
575
int ret;
576
577
if ((ret = pthread_mutex_lock(&lock->lock)))
578
ERR("Failed to lock the mutex, ret %d.\n", ret);
579
#endif
580
}
581
582
static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)
583
{
584
#ifdef _WIN32
585
LeaveCriticalSection(&lock->lock);
586
#else
587
int ret;
588
589
if ((ret = pthread_mutex_unlock(&lock->lock)))
590
ERR("Failed to unlock the mutex, ret %d.\n", ret);
591
#endif
592
}
593
594
static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)
595
{
596
#ifdef _WIN32
597
DeleteCriticalSection(&lock->lock);
598
#else
599
int ret;
600
601
if ((ret = pthread_mutex_destroy(&lock->lock)))
602
ERR("Failed to destroy the mutex, ret %d.\n", ret);
603
#endif
604
}
605
606
struct vkd3d_cond
607
{
608
#ifdef _WIN32
609
CONDITION_VARIABLE cond;
610
#else
611
pthread_cond_t cond;
612
#endif
613
};
614
615
static inline void vkd3d_cond_init(struct vkd3d_cond *cond)
616
{
617
#ifdef _WIN32
618
InitializeConditionVariable(&cond->cond);
619
#else
620
int ret;
621
622
if ((ret = pthread_cond_init(&cond->cond, NULL)))
623
ERR("Failed to initialise the condition variable, ret %d.\n", ret);
624
#endif
625
}
626
627
static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)
628
{
629
#ifdef _WIN32
630
WakeConditionVariable(&cond->cond);
631
#else
632
int ret;
633
634
if ((ret = pthread_cond_signal(&cond->cond)))
635
ERR("Failed to signal the condition variable, ret %d.\n", ret);
636
#endif
637
}
638
639
static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)
640
{
641
#ifdef _WIN32
642
WakeAllConditionVariable(&cond->cond);
643
#else
644
int ret;
645
646
if ((ret = pthread_cond_broadcast(&cond->cond)))
647
ERR("Failed to broadcast the condition variable, ret %d.\n", ret);
648
#endif
649
}
650
651
static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)
652
{
653
#ifdef _WIN32
654
if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))
655
ERR("Failed to wait on the condition variable, error %lu.\n", GetLastError());
656
#else
657
int ret;
658
659
if ((ret = pthread_cond_wait(&cond->cond, &lock->lock)))
660
ERR("Failed to wait on the condition variable, ret %d.\n", ret);
661
#endif
662
}
663
664
static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)
665
{
666
#ifdef _WIN32
667
/* Nothing to do. */
668
#else
669
int ret;
670
671
if ((ret = pthread_cond_destroy(&cond->cond)))
672
ERR("Failed to destroy the condition variable, ret %d.\n", ret);
673
#endif
674
}
675
676
static inline void vkd3d_parse_version(const char *version, int *major, int *minor)
677
{
678
*major = atoi(version);
679
680
while (isdigit(*version))
681
++version;
682
if (*version == '.')
683
++version;
684
685
*minor = atoi(version);
686
}
687
688
HRESULT hresult_from_vkd3d_result(int vkd3d_result);
689
690
#ifdef _WIN32
691
static inline void *vkd3d_dlopen(const char *name)
692
{
693
return LoadLibraryA(name);
694
}
695
696
static inline void *vkd3d_dlsym(void *handle, const char *symbol)
697
{
698
return GetProcAddress(handle, symbol);
699
}
700
701
static inline int vkd3d_dlclose(void *handle)
702
{
703
return FreeLibrary(handle);
704
}
705
706
static inline const char *vkd3d_dlerror(void)
707
{
708
unsigned int error = GetLastError();
709
static char message[256];
710
711
if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, message, sizeof(message), NULL))
712
return message;
713
sprintf(message, "Unknown error %u.\n", error);
714
return message;
715
}
716
#elif defined(HAVE_DLFCN_H)
717
#include <dlfcn.h>
718
719
static inline void *vkd3d_dlopen(const char *name)
720
{
721
return dlopen(name, RTLD_NOW);
722
}
723
724
static inline void *vkd3d_dlsym(void *handle, const char *symbol)
725
{
726
return dlsym(handle, symbol);
727
}
728
729
static inline int vkd3d_dlclose(void *handle)
730
{
731
return dlclose(handle);
732
}
733
734
static inline const char *vkd3d_dlerror(void)
735
{
736
return dlerror();
737
}
738
#else
739
static inline void *vkd3d_dlopen(const char *name)
740
{
741
return NULL;
742
}
743
744
static inline void *vkd3d_dlsym(void *handle, const char *symbol)
745
{
746
return NULL;
747
}
748
749
static inline int vkd3d_dlclose(void *handle)
750
{
751
return 0;
752
}
753
754
static inline const char *vkd3d_dlerror(void)
755
{
756
return "Not implemented for this platform.\n";
757
}
758
#endif
759
760
#endif /* __VKD3D_COMMON_H */
761
762