Path: blob/master/libs/vkd3d/include/private/vkd3d_common.h
8745 views
/*1* Copyright 2016 Józef Kucia for CodeWeavers2*3* This library is free software; you can redistribute it and/or4* modify it under the terms of the GNU Lesser General Public5* License as published by the Free Software Foundation; either6* version 2.1 of the License, or (at your option) any later version.7*8* This library is distributed in the hope that it will be useful,9* but WITHOUT ANY WARRANTY; without even the implied warranty of10* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU11* Lesser General Public License for more details.12*13* You should have received a copy of the GNU Lesser General Public14* License along with this library; if not, write to the Free Software15* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA16*/1718#ifndef __VKD3D_COMMON_H19#define __VKD3D_COMMON_H2021#ifndef VKD3D_DEBUG_ENV22#define VKD3D_DEBUG_ENV VKD3D_DEBUG23#endif24#define VKD3D_DEBUG_ENV_NAME VKD3D_EXPAND_AND_STRINGIFY(VKD3D_DEBUG_ENV)2526#include "config.h"27#define WIN32_LEAN_AND_MEAN28#include "windows.h"29#include "vkd3d_types.h"3031#include <ctype.h>32#include <limits.h>33#include <stdbool.h>34#include <stdint.h>35#include <stdio.h>36#include <stdlib.h>37#ifndef _WIN3238#include <pthread.h>39#endif4041#ifdef _MSC_VER42#include <intrin.h>43#endif4445#define VKD3D_SHADER_API_VERSION_CURRENT VKD3D_SHADER_API_VERSION_1_184647#ifndef ARRAY_SIZE48# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))49#endif5051#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)5253#define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])5455#define VKD3D_ASSERT(cond) \56do { \57if (!(cond)) \58ERR("Failed assertion: %s\n", #cond); \59} while (0)6061#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)6263#define VKD3D_MAKE_TAG(ch0, ch1, ch2, ch3) \64((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) \65| ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24))6667#define VKD3D_EXPAND(x) x68#define VKD3D_STRINGIFY(x) #x69#define VKD3D_EXPAND_AND_STRINGIFY(x) VKD3D_EXPAND(VKD3D_STRINGIFY(x))7071#define vkd3d_clamp(value, lower, upper) max(min(value, upper), lower)7273#define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9')74#define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4')75#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T')76#define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B')77#define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C')78#define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L')79#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0')80#define TAG_FXLC VKD3D_MAKE_TAG('F', 'X', 'L', 'C')81#define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1')82#define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N')83#define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1')84#define TAG_OSG5 VKD3D_MAKE_TAG('O', 'S', 'G', '5')85#define TAG_OSGN VKD3D_MAKE_TAG('O', 'S', 'G', 'N')86#define TAG_PCSG VKD3D_MAKE_TAG('P', 'C', 'S', 'G')87#define TAG_PSG1 VKD3D_MAKE_TAG('P', 'S', 'G', '1')88#define TAG_RD11 VKD3D_MAKE_TAG('R', 'D', '1', '1')89#define TAG_RDEF VKD3D_MAKE_TAG('R', 'D', 'E', 'F')90#define TAG_RTS0 VKD3D_MAKE_TAG('R', 'T', 'S', '0')91#define TAG_SDBG VKD3D_MAKE_TAG('S', 'D', 'B', 'G')92#define TAG_SFI0 VKD3D_MAKE_TAG('S', 'F', 'I', '0')93#define TAG_SHDR VKD3D_MAKE_TAG('S', 'H', 'D', 'R')94#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')95#define TAG_STAT VKD3D_MAKE_TAG('S', 'T', 'A', 'T')96#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')97#define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P')98#define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S')99100#define TAG_RD11_REVERSE 0x25441313101102static inline uint64_t align(uint64_t addr, size_t alignment)103{104return (addr + (alignment - 1)) & ~(alignment - 1);105}106107#if defined(__GNUC__) || defined(__clang__)108# define VKD3D_NORETURN __attribute__((noreturn))109# ifdef __MINGW_PRINTF_FORMAT110# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))111# else112# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))113# endif114# define VKD3D_UNUSED __attribute__((unused))115# define VKD3D_UNREACHABLE __builtin_unreachable()116#else117# define VKD3D_NORETURN118# define VKD3D_PRINTF_FUNC(fmt, args)119# define VKD3D_UNUSED120# define VKD3D_UNREACHABLE (void)0121#endif /* __GNUC__ */122123#define vkd3d_unreachable() \124do { \125ERR("%s:%u: Unreachable code reached.\n", __FILE__, __LINE__); \126VKD3D_UNREACHABLE; \127} while (0)128129#ifdef VKD3D_NO_TRACE_MESSAGES130#define TRACE(args...) do { } while (0)131#define TRACE_ON() (false)132#endif133134#ifdef VKD3D_NO_DEBUG_MESSAGES135#define WARN(args...) do { } while (0)136#define FIXME(args...) do { } while (0)137#define WARN_ON() (false)138#define FIXME_ONCE(args...) do { } while (0)139#endif140141#ifdef VKD3D_NO_ERROR_MESSAGES142#define ERR(args...) do { } while (0)143#define MESSAGE(args...) do { } while (0)144#endif145146enum vkd3d_dbg_level147{148VKD3D_DBG_LEVEL_NONE,149VKD3D_DBG_LEVEL_MESSAGE,150VKD3D_DBG_LEVEL_ERR,151VKD3D_DBG_LEVEL_FIXME,152VKD3D_DBG_LEVEL_WARN,153VKD3D_DBG_LEVEL_TRACE,154};155156enum vkd3d_dbg_level vkd3d_dbg_get_level(const char *vkd3d_dbg_env_name);157158void vkd3d_dbg_printf(const char *vkd3d_dbg_env_name, enum vkd3d_dbg_level level,159const char *function, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5);160void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback);161162const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2);163const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args);164const char *debugstr_a(const char *str);165const char *debugstr_an(const char *str, size_t n);166const char *debugstr_w(const WCHAR *wstr, size_t wchar_size);167168#define VKD3D_DBG_LOG(level) \169do { \170const enum vkd3d_dbg_level vkd3d_dbg_level = VKD3D_DBG_LEVEL_##level; \171VKD3D_DBG_PRINTF_##level172173#define VKD3D_DBG_LOG_ONCE(first_time_level, level) \174do { \175static bool vkd3d_dbg_next_time; \176const enum vkd3d_dbg_level vkd3d_dbg_level = vkd3d_dbg_next_time \177? VKD3D_DBG_LEVEL_##level : VKD3D_DBG_LEVEL_##first_time_level; \178vkd3d_dbg_next_time = true; \179VKD3D_DBG_PRINTF_##level180181#define VKD3D_DBG_PRINTF(...) \182vkd3d_dbg_printf(VKD3D_DEBUG_ENV_NAME, vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)183184#define VKD3D_DBG_PRINTF_TRACE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)185#define VKD3D_DBG_PRINTF_WARN(...) VKD3D_DBG_PRINTF(__VA_ARGS__)186#define VKD3D_DBG_PRINTF_FIXME(...) VKD3D_DBG_PRINTF(__VA_ARGS__)187#define VKD3D_DBG_PRINTF_MESSAGE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)188189#ifdef VKD3D_ABORT_ON_ERR190#define VKD3D_DBG_PRINTF_ERR(...) \191vkd3d_dbg_printf(VKD3D_DEBUG_ENV_NAME, vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); \192abort(); \193} while (0)194#else195#define VKD3D_DBG_PRINTF_ERR(...) VKD3D_DBG_PRINTF(__VA_ARGS__)196#endif197198/* Used by vkd3d_unreachable(). */199#ifdef VKD3D_CROSSTEST200#undef ERR201#define ERR(...) do { fprintf(stderr, __VA_ARGS__); abort(); } while (0)202#endif203204#ifndef TRACE205#define TRACE VKD3D_DBG_LOG(TRACE)206#endif207208#ifndef WARN209#define WARN VKD3D_DBG_LOG(WARN)210#endif211212#ifndef FIXME213#define FIXME VKD3D_DBG_LOG(FIXME)214#endif215216#ifndef ERR217#define ERR VKD3D_DBG_LOG(ERR)218#endif219220#ifndef MESSAGE221#define MESSAGE VKD3D_DBG_LOG(MESSAGE)222#endif223224#ifndef TRACE_ON225#define TRACE_ON() (vkd3d_dbg_get_level(VKD3D_DEBUG_ENV_NAME) == VKD3D_DBG_LEVEL_TRACE)226#endif227228#ifndef WARN_ON229#define WARN_ON() (vkd3d_dbg_get_level(VKD3D_DEBUG_ENV_NAME) >= VKD3D_DBG_LEVEL_WARN)230#endif231232#ifndef FIXME_ONCE233#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)234#endif235236static inline const char *debugstr_guid(const GUID *guid)237{238if (!guid)239return "(null)";240241return vkd3d_dbg_sprintf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",242(unsigned long)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],243guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],244guid->Data4[5], guid->Data4[6], guid->Data4[7]);245}246247static inline const char *debugstr_hresult(HRESULT hr)248{249switch (hr)250{251#define TO_STR(u) case u: return #u;252TO_STR(S_OK)253TO_STR(S_FALSE)254TO_STR(E_NOTIMPL)255TO_STR(E_NOINTERFACE)256TO_STR(E_POINTER)257TO_STR(E_ABORT)258TO_STR(E_FAIL)259TO_STR(E_OUTOFMEMORY)260TO_STR(E_INVALIDARG)261TO_STR(DXGI_ERROR_NOT_FOUND)262TO_STR(DXGI_ERROR_MORE_DATA)263TO_STR(DXGI_ERROR_UNSUPPORTED)264#undef TO_STR265default:266return vkd3d_dbg_sprintf("%#x", (int)hr);267}268}269270unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value);271272struct vkd3d_debug_option273{274const char *name;275uint64_t flag;276};277278bool vkd3d_debug_list_has_member(const char *string, const char *member);279uint64_t vkd3d_parse_debug_options(const char *string,280const struct vkd3d_debug_option *options, unsigned int option_count);281void vkd3d_set_thread_name(const char *name);282283static inline unsigned int vkd3d_popcount(unsigned int v)284{285#ifdef _MSC_VER286return __popcnt(v);287#elif defined(__MINGW32__)288return __builtin_popcount(v);289#else290v -= (v >> 1) & 0x55555555;291v = (v & 0x33333333) + ((v >> 2) & 0x33333333);292return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;293#endif294}295296static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask)297{298unsigned int i, j;299300for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i)301{302if (mask & (1u << i))303++j;304else if (j)305break;306}307308return vkd3d_popcount(mask) == j;309}310311/* Undefined for x == 0. */312static inline unsigned int vkd3d_log2i(unsigned int x)313{314#ifdef _WIN32315/* _BitScanReverse returns the index of the highest set bit,316* unlike clz which is 31 - index. */317ULONG result;318_BitScanReverse(&result, x);319return (unsigned int)result;320#elif defined(HAVE_BUILTIN_CLZ)321return __builtin_clz(x) ^ 0x1f;322#else323static const unsigned int l[] =324{325~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,3264, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,3275, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,3285, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,3296, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3306, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3316, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3326, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3337, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3347, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3357, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3367, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3377, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3387, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3397, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3407, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,341};342unsigned int i;343344return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24345: l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];346#endif347}348349static inline unsigned int vkd3d_ctz(uint32_t v)350{351#ifdef _WIN32352ULONG result;353if (_BitScanForward(&result, v))354return (unsigned int)result;355return 32;356#elif defined(HAVE_BUILTIN_CTZ)357return __builtin_ctz(v);358#else359unsigned int c = 31;360361v &= -v;362c = (v & 0x0000ffff) ? c - 16 : c;363c = (v & 0x00ff00ff) ? c - 8 : c;364c = (v & 0x0f0f0f0f) ? c - 4 : c;365c = (v & 0x33333333) ? c - 2 : c;366c = (v & 0x55555555) ? c - 1 : c;367368return c;369#endif370}371372static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)373{374const char *str = haystack;375376while (haystack_len >= needle_len)377{378if (!memcmp(str, needle, needle_len))379return (char *)str;380++str;381--haystack_len;382}383return NULL;384}385386static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit)387{388#ifdef HAVE_BUILTIN_ADD_OVERFLOW389size_t sum;390391return !__builtin_add_overflow(start, count, &sum) && sum <= limit;392#else393return start <= limit && count <= limit - start;394#endif395}396397static inline bool vkd3d_object_range_overflow(size_t start, size_t count, size_t size)398{399return (~(size_t)0 - start) / size < count;400}401402static inline uint16_t vkd3d_make_u16(uint8_t low, uint8_t high)403{404return low | ((uint16_t)high << 8);405}406407static inline uint32_t vkd3d_make_u32(uint16_t low, uint16_t high)408{409return low | ((uint32_t)high << 16);410}411412static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)413{414return (x > y) - (x < y);415}416417static inline int vkd3d_u64_compare(uint64_t x, uint64_t y)418{419return (x > y) - (x < y);420}421422#define VKD3D_BITMAP_SIZE(x) (((x) + 0x1f) >> 5)423424static inline bool bitmap_clear(uint32_t *map, unsigned int idx)425{426return map[idx >> 5] &= ~(1u << (idx & 0x1f));427}428429static inline bool bitmap_set(uint32_t *map, unsigned int idx)430{431return map[idx >> 5] |= (1u << (idx & 0x1f));432}433434static inline bool bitmap_is_set(const uint32_t *map, unsigned int idx)435{436return map[idx >> 5] & (1u << (idx & 0x1f));437}438439static inline int ascii_isupper(int c)440{441return 'A' <= c && c <= 'Z';442}443444static inline int ascii_tolower(int c)445{446return ascii_isupper(c) ? c - 'A' + 'a' : c;447}448449static inline int ascii_strncasecmp(const char *a, const char *b, size_t n)450{451int c_a, c_b;452453while (n--)454{455c_a = ascii_tolower(*a++);456c_b = ascii_tolower(*b++);457if (c_a != c_b || !c_a)458return c_a - c_b;459}460return 0;461}462463static inline int ascii_strcasecmp(const char *a, const char *b)464{465int c_a, c_b;466467do468{469c_a = ascii_tolower(*a++);470c_b = ascii_tolower(*b++);471} while (c_a == c_b && c_a != '\0');472473return c_a - c_b;474}475476static inline uint64_t vkd3d_atomic_add_fetch_u64(uint64_t volatile *x, uint64_t val)477{478#if HAVE_SYNC_ADD_AND_FETCH479return __sync_add_and_fetch(x, val);480#elif defined(_WIN32)481return InterlockedAdd64((LONG64 *)x, val);482#else483# error "vkd3d_atomic_add_fetch_u64() not implemented for this platform"484#endif485}486487static inline uint32_t vkd3d_atomic_add_fetch_u32(uint32_t volatile *x, uint32_t val)488{489#if HAVE_SYNC_ADD_AND_FETCH490return __sync_add_and_fetch(x, val);491#elif defined(_WIN32)492return InterlockedAdd((LONG *)x, val);493#else494# error "vkd3d_atomic_add_fetch_u32() not implemented for this platform"495#endif496}497498static inline uint64_t vkd3d_atomic_increment_u64(uint64_t volatile *x)499{500return vkd3d_atomic_add_fetch_u64(x, 1);501}502503static inline uint32_t vkd3d_atomic_decrement_u32(uint32_t volatile *x)504{505return vkd3d_atomic_add_fetch_u32(x, ~0u);506}507508static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)509{510return vkd3d_atomic_add_fetch_u32(x, 1);511}512513static inline bool vkd3d_atomic_compare_exchange_u32(uint32_t volatile *x, uint32_t expected, uint32_t val)514{515#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP516return __sync_bool_compare_and_swap(x, expected, val);517#elif defined(_WIN32)518return InterlockedCompareExchange((LONG *)x, val, expected) == expected;519#else520# error "vkd3d_atomic_compare_exchange_u32() not implemented for this platform"521#endif522}523524static inline bool vkd3d_atomic_compare_exchange_ptr(void * volatile *x, void *expected, void *val)525{526#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP527return __sync_bool_compare_and_swap(x, expected, val);528#elif defined(_WIN32)529return InterlockedCompareExchangePointer(x, val, expected) == expected;530#else531# error "vkd3d_atomic_compare_exchange_ptr() not implemented for this platform"532#endif533}534535static inline uint32_t vkd3d_atomic_exchange_u32(uint32_t volatile *x, uint32_t val)536{537#if HAVE_ATOMIC_EXCHANGE_N538return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);539#elif defined(_WIN32)540return InterlockedExchange((LONG *)x, val);541#else542uint32_t expected;543544do545{546expected = *x;547} while (!vkd3d_atomic_compare_exchange_u32(x, expected, val));548549return expected;550#endif551}552553static inline void *vkd3d_atomic_exchange_ptr(void * volatile *x, void *val)554{555#if HAVE_ATOMIC_EXCHANGE_N556return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);557#elif defined(_WIN32)558return InterlockedExchangePointer(x, val);559#else560void *expected;561562do563{564expected = *x;565} while (!vkd3d_atomic_compare_exchange_ptr(x, expected, val));566567return expected;568#endif569}570571struct vkd3d_mutex572{573#ifdef _WIN32574CRITICAL_SECTION lock;575#else576pthread_mutex_t lock;577#endif578};579580#ifdef _WIN32581#define VKD3D_MUTEX_INITIALIZER {{NULL, -1, 0, 0, 0, 0}}582#else583#define VKD3D_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER584#endif585586static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)587{588#ifdef _WIN32589InitializeCriticalSection(&lock->lock);590#else591int ret;592593if ((ret = pthread_mutex_init(&lock->lock, NULL)))594ERR("Failed to initialise the mutex, ret %d.\n", ret);595#endif596}597598static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)599{600#ifdef _WIN32601EnterCriticalSection(&lock->lock);602#else603int ret;604605if ((ret = pthread_mutex_lock(&lock->lock)))606ERR("Failed to lock the mutex, ret %d.\n", ret);607#endif608}609610static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)611{612#ifdef _WIN32613LeaveCriticalSection(&lock->lock);614#else615int ret;616617if ((ret = pthread_mutex_unlock(&lock->lock)))618ERR("Failed to unlock the mutex, ret %d.\n", ret);619#endif620}621622static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)623{624#ifdef _WIN32625DeleteCriticalSection(&lock->lock);626#else627int ret;628629if ((ret = pthread_mutex_destroy(&lock->lock)))630ERR("Failed to destroy the mutex, ret %d.\n", ret);631#endif632}633634struct vkd3d_cond635{636#ifdef _WIN32637CONDITION_VARIABLE cond;638#else639pthread_cond_t cond;640#endif641};642643static inline void vkd3d_cond_init(struct vkd3d_cond *cond)644{645#ifdef _WIN32646InitializeConditionVariable(&cond->cond);647#else648int ret;649650if ((ret = pthread_cond_init(&cond->cond, NULL)))651ERR("Failed to initialise the condition variable, ret %d.\n", ret);652#endif653}654655static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)656{657#ifdef _WIN32658WakeConditionVariable(&cond->cond);659#else660int ret;661662if ((ret = pthread_cond_signal(&cond->cond)))663ERR("Failed to signal the condition variable, ret %d.\n", ret);664#endif665}666667static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)668{669#ifdef _WIN32670WakeAllConditionVariable(&cond->cond);671#else672int ret;673674if ((ret = pthread_cond_broadcast(&cond->cond)))675ERR("Failed to broadcast the condition variable, ret %d.\n", ret);676#endif677}678679static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)680{681#ifdef _WIN32682if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))683ERR("Failed to wait on the condition variable, error %lu.\n", GetLastError());684#else685int ret;686687if ((ret = pthread_cond_wait(&cond->cond, &lock->lock)))688ERR("Failed to wait on the condition variable, ret %d.\n", ret);689#endif690}691692static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)693{694#ifdef _WIN32695/* Nothing to do. */696#else697int ret;698699if ((ret = pthread_cond_destroy(&cond->cond)))700ERR("Failed to destroy the condition variable, ret %d.\n", ret);701#endif702}703704static inline void vkd3d_parse_version(const char *version, int *major, int *minor)705{706*major = atoi(version);707708while (isdigit(*version))709++version;710if (*version == '.')711++version;712713*minor = atoi(version);714}715716HRESULT hresult_from_vkd3d_result(int vkd3d_result);717718#ifdef _WIN32719static inline void *vkd3d_dlopen(const char *name)720{721return LoadLibraryA(name);722}723724static inline void *vkd3d_dlsym(void *handle, const char *symbol)725{726return GetProcAddress(handle, symbol);727}728729static inline int vkd3d_dlclose(void *handle)730{731return FreeLibrary(handle);732}733734static inline const char *vkd3d_dlerror(void)735{736unsigned int error = GetLastError();737static char message[256];738739if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, message, sizeof(message), NULL))740return message;741sprintf(message, "Unknown error %u.\n", error);742return message;743}744#elif defined(HAVE_DLFCN_H)745#include <dlfcn.h>746747static inline void *vkd3d_dlopen(const char *name)748{749return dlopen(name, RTLD_NOW);750}751752static inline void *vkd3d_dlsym(void *handle, const char *symbol)753{754return dlsym(handle, symbol);755}756757static inline int vkd3d_dlclose(void *handle)758{759return dlclose(handle);760}761762static inline const char *vkd3d_dlerror(void)763{764return dlerror();765}766#else767static inline void *vkd3d_dlopen(const char *name)768{769return NULL;770}771772static inline void *vkd3d_dlsym(void *handle, const char *symbol)773{774return NULL;775}776777static inline int vkd3d_dlclose(void *handle)778{779return 0;780}781782static inline const char *vkd3d_dlerror(void)783{784return "Not implemented for this platform.\n";785}786#endif787788#endif /* __VKD3D_COMMON_H */789790791