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