Path: blob/master/libs/vkd3d/include/private/vkd3d_common.h
4393 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#include "config.h"22#define WIN32_LEAN_AND_MEAN23#include "windows.h"24#include "vkd3d_types.h"2526#include <ctype.h>27#include <limits.h>28#include <stdbool.h>29#include <stdint.h>30#include <stdio.h>31#include <stdlib.h>32#ifndef _WIN3233#include <pthread.h>34#endif3536#ifdef _MSC_VER37#include <intrin.h>38#endif3940#ifndef ARRAY_SIZE41# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))42#endif4344#define DIV_ROUND_UP(a, b) ((a) % (b) == 0 ? (a) / (b) : (a) / (b) + 1)4546#define STATIC_ASSERT(e) extern void __VKD3D_STATIC_ASSERT__(int [(e) ? 1 : -1])4748#define VKD3D_ASSERT(cond) \49do { \50if (!(cond)) \51ERR("Failed assertion: %s\n", #cond); \52} while (0)5354#define MEMBER_SIZE(t, m) sizeof(((t *)0)->m)5556#define VKD3D_MAKE_TAG(ch0, ch1, ch2, ch3) \57((uint32_t)(ch0) | ((uint32_t)(ch1) << 8) \58| ((uint32_t)(ch2) << 16) | ((uint32_t)(ch3) << 24))5960#define VKD3D_EXPAND(x) x61#define VKD3D_STRINGIFY(x) #x62#define VKD3D_EXPAND_AND_STRINGIFY(x) VKD3D_EXPAND(VKD3D_STRINGIFY(x))6364#define vkd3d_clamp(value, lower, upper) max(min(value, upper), lower)6566#define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9')67#define TAG_CLI4 VKD3D_MAKE_TAG('C', 'L', 'I', '4')68#define TAG_CLIT VKD3D_MAKE_TAG('C', 'L', 'I', 'T')69#define TAG_CTAB VKD3D_MAKE_TAG('C', 'T', 'A', 'B')70#define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C')71#define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L')72#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0')73#define TAG_FXLC VKD3D_MAKE_TAG('F', 'X', 'L', 'C')74#define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1')75#define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N')76#define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1')77#define TAG_OSG5 VKD3D_MAKE_TAG('O', 'S', 'G', '5')78#define TAG_OSGN VKD3D_MAKE_TAG('O', 'S', 'G', 'N')79#define TAG_PCSG VKD3D_MAKE_TAG('P', 'C', 'S', 'G')80#define TAG_PSG1 VKD3D_MAKE_TAG('P', 'S', 'G', '1')81#define TAG_RD11 VKD3D_MAKE_TAG('R', 'D', '1', '1')82#define TAG_RDEF VKD3D_MAKE_TAG('R', 'D', 'E', 'F')83#define TAG_RTS0 VKD3D_MAKE_TAG('R', 'T', 'S', '0')84#define TAG_SDBG VKD3D_MAKE_TAG('S', 'D', 'B', 'G')85#define TAG_SFI0 VKD3D_MAKE_TAG('S', 'F', 'I', '0')86#define TAG_SHDR VKD3D_MAKE_TAG('S', 'H', 'D', 'R')87#define TAG_SHEX VKD3D_MAKE_TAG('S', 'H', 'E', 'X')88#define TAG_STAT VKD3D_MAKE_TAG('S', 'T', 'A', 'T')89#define TAG_TEXT VKD3D_MAKE_TAG('T', 'E', 'X', 'T')90#define TAG_XNAP VKD3D_MAKE_TAG('X', 'N', 'A', 'P')91#define TAG_XNAS VKD3D_MAKE_TAG('X', 'N', 'A', 'S')9293#define TAG_RD11_REVERSE 0x254413139495static inline uint64_t align(uint64_t addr, size_t alignment)96{97return (addr + (alignment - 1)) & ~(alignment - 1);98}99100#if defined(__GNUC__) || defined(__clang__)101# define VKD3D_NORETURN __attribute__((noreturn))102# ifdef __MINGW_PRINTF_FORMAT103# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(__MINGW_PRINTF_FORMAT, fmt, args)))104# else105# define VKD3D_PRINTF_FUNC(fmt, args) __attribute__((format(printf, fmt, args)))106# endif107# define VKD3D_UNUSED __attribute__((unused))108# define VKD3D_UNREACHABLE __builtin_unreachable()109#else110# define VKD3D_NORETURN111# define VKD3D_PRINTF_FUNC(fmt, args)112# define VKD3D_UNUSED113# define VKD3D_UNREACHABLE (void)0114#endif /* __GNUC__ */115116#define vkd3d_unreachable() \117do { \118ERR("%s:%u: Unreachable code reached.\n", __FILE__, __LINE__); \119VKD3D_UNREACHABLE; \120} while (0)121122#ifdef VKD3D_NO_TRACE_MESSAGES123#define TRACE(args...) do { } while (0)124#define TRACE_ON() (false)125#endif126127#ifdef VKD3D_NO_DEBUG_MESSAGES128#define WARN(args...) do { } while (0)129#define FIXME(args...) do { } while (0)130#define WARN_ON() (false)131#define FIXME_ONCE(args...) do { } while (0)132#endif133134#ifdef VKD3D_NO_ERROR_MESSAGES135#define ERR(args...) do { } while (0)136#define MESSAGE(args...) do { } while (0)137#endif138139enum vkd3d_dbg_level140{141VKD3D_DBG_LEVEL_NONE,142VKD3D_DBG_LEVEL_MESSAGE,143VKD3D_DBG_LEVEL_ERR,144VKD3D_DBG_LEVEL_FIXME,145VKD3D_DBG_LEVEL_WARN,146VKD3D_DBG_LEVEL_TRACE,147};148149enum vkd3d_dbg_level vkd3d_dbg_get_level(void);150151void vkd3d_dbg_printf(enum vkd3d_dbg_level level, const char *function, const char *fmt, ...) VKD3D_PRINTF_FUNC(3, 4);152void vkd3d_dbg_set_log_callback(PFN_vkd3d_log callback);153154const char *vkd3d_dbg_sprintf(const char *fmt, ...) VKD3D_PRINTF_FUNC(1, 2);155const char *vkd3d_dbg_vsprintf(const char *fmt, va_list args);156const char *debugstr_a(const char *str);157const char *debugstr_an(const char *str, size_t n);158const char *debugstr_w(const WCHAR *wstr, size_t wchar_size);159160#define VKD3D_DBG_LOG(level) \161do { \162const enum vkd3d_dbg_level vkd3d_dbg_level = VKD3D_DBG_LEVEL_##level; \163VKD3D_DBG_PRINTF_##level164165#define VKD3D_DBG_LOG_ONCE(first_time_level, level) \166do { \167static bool vkd3d_dbg_next_time; \168const enum vkd3d_dbg_level vkd3d_dbg_level = vkd3d_dbg_next_time \169? VKD3D_DBG_LEVEL_##level : VKD3D_DBG_LEVEL_##first_time_level; \170vkd3d_dbg_next_time = true; \171VKD3D_DBG_PRINTF_##level172173#define VKD3D_DBG_PRINTF(...) \174vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)175176#define VKD3D_DBG_PRINTF_TRACE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)177#define VKD3D_DBG_PRINTF_WARN(...) VKD3D_DBG_PRINTF(__VA_ARGS__)178#define VKD3D_DBG_PRINTF_FIXME(...) VKD3D_DBG_PRINTF(__VA_ARGS__)179#define VKD3D_DBG_PRINTF_MESSAGE(...) VKD3D_DBG_PRINTF(__VA_ARGS__)180181#ifdef VKD3D_ABORT_ON_ERR182#define VKD3D_DBG_PRINTF_ERR(...) \183vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); \184abort(); \185} while (0)186#else187#define VKD3D_DBG_PRINTF_ERR(...) VKD3D_DBG_PRINTF(__VA_ARGS__)188#endif189190/* Used by vkd3d_unreachable(). */191#ifdef VKD3D_CROSSTEST192#undef ERR193#define ERR(...) do { fprintf(stderr, __VA_ARGS__); abort(); } while (0)194#endif195196#ifndef TRACE197#define TRACE VKD3D_DBG_LOG(TRACE)198#endif199200#ifndef WARN201#define WARN VKD3D_DBG_LOG(WARN)202#endif203204#ifndef FIXME205#define FIXME VKD3D_DBG_LOG(FIXME)206#endif207208#ifndef ERR209#define ERR VKD3D_DBG_LOG(ERR)210#endif211212#ifndef MESSAGE213#define MESSAGE VKD3D_DBG_LOG(MESSAGE)214#endif215216#ifndef TRACE_ON217#define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE)218#endif219220#ifndef WARN_ON221#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN)222#endif223224#ifndef FIXME_ONCE225#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)226#endif227228#define VKD3D_DEBUG_ENV_NAME(name) const char *const vkd3d_dbg_env_name = name229230static inline const char *debugstr_guid(const GUID *guid)231{232if (!guid)233return "(null)";234235return vkd3d_dbg_sprintf("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",236(unsigned long)guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],237guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],238guid->Data4[5], guid->Data4[6], guid->Data4[7]);239}240241static inline const char *debugstr_hresult(HRESULT hr)242{243switch (hr)244{245#define TO_STR(u) case u: return #u;246TO_STR(S_OK)247TO_STR(S_FALSE)248TO_STR(E_NOTIMPL)249TO_STR(E_NOINTERFACE)250TO_STR(E_POINTER)251TO_STR(E_ABORT)252TO_STR(E_FAIL)253TO_STR(E_OUTOFMEMORY)254TO_STR(E_INVALIDARG)255TO_STR(DXGI_ERROR_NOT_FOUND)256TO_STR(DXGI_ERROR_MORE_DATA)257TO_STR(DXGI_ERROR_UNSUPPORTED)258#undef TO_STR259default:260return vkd3d_dbg_sprintf("%#x", (int)hr);261}262}263264unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value);265266struct vkd3d_debug_option267{268const char *name;269uint64_t flag;270};271272bool vkd3d_debug_list_has_member(const char *string, const char *member);273uint64_t vkd3d_parse_debug_options(const char *string,274const struct vkd3d_debug_option *options, unsigned int option_count);275void vkd3d_set_thread_name(const char *name);276277static inline unsigned int vkd3d_popcount(unsigned int v)278{279#ifdef _MSC_VER280return __popcnt(v);281#elif defined(__MINGW32__)282return __builtin_popcount(v);283#else284v -= (v >> 1) & 0x55555555;285v = (v & 0x33333333) + ((v >> 2) & 0x33333333);286return (((v + (v >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;287#endif288}289290static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask)291{292unsigned int i, j;293294for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i)295{296if (mask & (1u << i))297++j;298else if (j)299break;300}301302return vkd3d_popcount(mask) == j;303}304305/* Undefined for x == 0. */306static inline unsigned int vkd3d_log2i(unsigned int x)307{308#ifdef _WIN32309/* _BitScanReverse returns the index of the highest set bit,310* unlike clz which is 31 - index. */311ULONG result;312_BitScanReverse(&result, x);313return (unsigned int)result;314#elif defined(HAVE_BUILTIN_CLZ)315return __builtin_clz(x) ^ 0x1f;316#else317static const unsigned int l[] =318{319~0u, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,3204, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,3215, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,3225, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,3236, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3246, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3256, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3266, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,3277, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3287, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3297, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3307, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3317, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,3327, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,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,335};336unsigned int i;337338return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24339: l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];340#endif341}342343static inline void *vkd3d_memmem( const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)344{345const char *str = haystack;346347while (haystack_len >= needle_len)348{349if (!memcmp(str, needle, needle_len))350return (char *)str;351++str;352--haystack_len;353}354return NULL;355}356357static inline bool vkd3d_bound_range(size_t start, size_t count, size_t limit)358{359#ifdef HAVE_BUILTIN_ADD_OVERFLOW360size_t sum;361362return !__builtin_add_overflow(start, count, &sum) && sum <= limit;363#else364return start <= limit && count <= limit - start;365#endif366}367368static inline bool vkd3d_object_range_overflow(size_t start, size_t count, size_t size)369{370return (~(size_t)0 - start) / size < count;371}372373static inline uint16_t vkd3d_make_u16(uint8_t low, uint8_t high)374{375return low | ((uint16_t)high << 8);376}377378static inline uint32_t vkd3d_make_u32(uint16_t low, uint16_t high)379{380return low | ((uint32_t)high << 16);381}382383static inline int vkd3d_u32_compare(uint32_t x, uint32_t y)384{385return (x > y) - (x < y);386}387388static inline int vkd3d_u64_compare(uint64_t x, uint64_t y)389{390return (x > y) - (x < y);391}392393#define VKD3D_BITMAP_SIZE(x) (((x) + 0x1f) >> 5)394395static inline bool bitmap_clear(uint32_t *map, unsigned int idx)396{397return map[idx >> 5] &= ~(1u << (idx & 0x1f));398}399400static inline bool bitmap_set(uint32_t *map, unsigned int idx)401{402return map[idx >> 5] |= (1u << (idx & 0x1f));403}404405static inline bool bitmap_is_set(const uint32_t *map, unsigned int idx)406{407return map[idx >> 5] & (1u << (idx & 0x1f));408}409410static inline int ascii_isupper(int c)411{412return 'A' <= c && c <= 'Z';413}414415static inline int ascii_tolower(int c)416{417return ascii_isupper(c) ? c - 'A' + 'a' : c;418}419420static inline int ascii_strncasecmp(const char *a, const char *b, size_t n)421{422int c_a, c_b;423424while (n--)425{426c_a = ascii_tolower(*a++);427c_b = ascii_tolower(*b++);428if (c_a != c_b || !c_a)429return c_a - c_b;430}431return 0;432}433434static inline int ascii_strcasecmp(const char *a, const char *b)435{436int c_a, c_b;437438do439{440c_a = ascii_tolower(*a++);441c_b = ascii_tolower(*b++);442} while (c_a == c_b && c_a != '\0');443444return c_a - c_b;445}446447static inline uint64_t vkd3d_atomic_add_fetch_u64(uint64_t volatile *x, uint64_t val)448{449#if HAVE_SYNC_ADD_AND_FETCH450return __sync_add_and_fetch(x, val);451#elif defined(_WIN32)452return InterlockedAdd64((LONG64 *)x, val);453#else454# error "vkd3d_atomic_add_fetch_u64() not implemented for this platform"455#endif456}457458static inline uint32_t vkd3d_atomic_add_fetch_u32(uint32_t volatile *x, uint32_t val)459{460#if HAVE_SYNC_ADD_AND_FETCH461return __sync_add_and_fetch(x, val);462#elif defined(_WIN32)463return InterlockedAdd((LONG *)x, val);464#else465# error "vkd3d_atomic_add_fetch_u32() not implemented for this platform"466#endif467}468469static inline uint64_t vkd3d_atomic_increment_u64(uint64_t volatile *x)470{471return vkd3d_atomic_add_fetch_u64(x, 1);472}473474static inline uint32_t vkd3d_atomic_decrement_u32(uint32_t volatile *x)475{476return vkd3d_atomic_add_fetch_u32(x, ~0u);477}478479static inline uint32_t vkd3d_atomic_increment_u32(uint32_t volatile *x)480{481return vkd3d_atomic_add_fetch_u32(x, 1);482}483484static inline bool vkd3d_atomic_compare_exchange_u32(uint32_t volatile *x, uint32_t expected, uint32_t val)485{486#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP487return __sync_bool_compare_and_swap(x, expected, val);488#elif defined(_WIN32)489return InterlockedCompareExchange((LONG *)x, val, expected) == expected;490#else491# error "vkd3d_atomic_compare_exchange_u32() not implemented for this platform"492#endif493}494495static inline bool vkd3d_atomic_compare_exchange_ptr(void * volatile *x, void *expected, void *val)496{497#if HAVE_SYNC_BOOL_COMPARE_AND_SWAP498return __sync_bool_compare_and_swap(x, expected, val);499#elif defined(_WIN32)500return InterlockedCompareExchangePointer(x, val, expected) == expected;501#else502# error "vkd3d_atomic_compare_exchange_ptr() not implemented for this platform"503#endif504}505506static inline uint32_t vkd3d_atomic_exchange_u32(uint32_t volatile *x, uint32_t val)507{508#if HAVE_ATOMIC_EXCHANGE_N509return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);510#elif defined(_WIN32)511return InterlockedExchange((LONG *)x, val);512#else513uint32_t expected;514515do516{517expected = *x;518} while (!vkd3d_atomic_compare_exchange_u32(x, expected, val));519520return expected;521#endif522}523524static inline void *vkd3d_atomic_exchange_ptr(void * volatile *x, void *val)525{526#if HAVE_ATOMIC_EXCHANGE_N527return __atomic_exchange_n(x, val, __ATOMIC_SEQ_CST);528#elif defined(_WIN32)529return InterlockedExchangePointer(x, val);530#else531void *expected;532533do534{535expected = *x;536} while (!vkd3d_atomic_compare_exchange_ptr(x, expected, val));537538return expected;539#endif540}541542struct vkd3d_mutex543{544#ifdef _WIN32545CRITICAL_SECTION lock;546#else547pthread_mutex_t lock;548#endif549};550551#ifdef _WIN32552#define VKD3D_MUTEX_INITIALIZER {{NULL, -1, 0, 0, 0, 0}}553#else554#define VKD3D_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER555#endif556557static inline void vkd3d_mutex_init(struct vkd3d_mutex *lock)558{559#ifdef _WIN32560InitializeCriticalSection(&lock->lock);561#else562int ret;563564if ((ret = pthread_mutex_init(&lock->lock, NULL)))565ERR("Failed to initialise the mutex, ret %d.\n", ret);566#endif567}568569static inline void vkd3d_mutex_lock(struct vkd3d_mutex *lock)570{571#ifdef _WIN32572EnterCriticalSection(&lock->lock);573#else574int ret;575576if ((ret = pthread_mutex_lock(&lock->lock)))577ERR("Failed to lock the mutex, ret %d.\n", ret);578#endif579}580581static inline void vkd3d_mutex_unlock(struct vkd3d_mutex *lock)582{583#ifdef _WIN32584LeaveCriticalSection(&lock->lock);585#else586int ret;587588if ((ret = pthread_mutex_unlock(&lock->lock)))589ERR("Failed to unlock the mutex, ret %d.\n", ret);590#endif591}592593static inline void vkd3d_mutex_destroy(struct vkd3d_mutex *lock)594{595#ifdef _WIN32596DeleteCriticalSection(&lock->lock);597#else598int ret;599600if ((ret = pthread_mutex_destroy(&lock->lock)))601ERR("Failed to destroy the mutex, ret %d.\n", ret);602#endif603}604605struct vkd3d_cond606{607#ifdef _WIN32608CONDITION_VARIABLE cond;609#else610pthread_cond_t cond;611#endif612};613614static inline void vkd3d_cond_init(struct vkd3d_cond *cond)615{616#ifdef _WIN32617InitializeConditionVariable(&cond->cond);618#else619int ret;620621if ((ret = pthread_cond_init(&cond->cond, NULL)))622ERR("Failed to initialise the condition variable, ret %d.\n", ret);623#endif624}625626static inline void vkd3d_cond_signal(struct vkd3d_cond *cond)627{628#ifdef _WIN32629WakeConditionVariable(&cond->cond);630#else631int ret;632633if ((ret = pthread_cond_signal(&cond->cond)))634ERR("Failed to signal the condition variable, ret %d.\n", ret);635#endif636}637638static inline void vkd3d_cond_broadcast(struct vkd3d_cond *cond)639{640#ifdef _WIN32641WakeAllConditionVariable(&cond->cond);642#else643int ret;644645if ((ret = pthread_cond_broadcast(&cond->cond)))646ERR("Failed to broadcast the condition variable, ret %d.\n", ret);647#endif648}649650static inline void vkd3d_cond_wait(struct vkd3d_cond *cond, struct vkd3d_mutex *lock)651{652#ifdef _WIN32653if (!SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE))654ERR("Failed to wait on the condition variable, error %lu.\n", GetLastError());655#else656int ret;657658if ((ret = pthread_cond_wait(&cond->cond, &lock->lock)))659ERR("Failed to wait on the condition variable, ret %d.\n", ret);660#endif661}662663static inline void vkd3d_cond_destroy(struct vkd3d_cond *cond)664{665#ifdef _WIN32666/* Nothing to do. */667#else668int ret;669670if ((ret = pthread_cond_destroy(&cond->cond)))671ERR("Failed to destroy the condition variable, ret %d.\n", ret);672#endif673}674675static inline void vkd3d_parse_version(const char *version, int *major, int *minor)676{677*major = atoi(version);678679while (isdigit(*version))680++version;681if (*version == '.')682++version;683684*minor = atoi(version);685}686687HRESULT hresult_from_vkd3d_result(int vkd3d_result);688689#ifdef _WIN32690static inline void *vkd3d_dlopen(const char *name)691{692return LoadLibraryA(name);693}694695static inline void *vkd3d_dlsym(void *handle, const char *symbol)696{697return GetProcAddress(handle, symbol);698}699700static inline int vkd3d_dlclose(void *handle)701{702return FreeLibrary(handle);703}704705static inline const char *vkd3d_dlerror(void)706{707unsigned int error = GetLastError();708static char message[256];709710if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, message, sizeof(message), NULL))711return message;712sprintf(message, "Unknown error %u.\n", error);713return message;714}715#elif defined(HAVE_DLFCN_H)716#include <dlfcn.h>717718static inline void *vkd3d_dlopen(const char *name)719{720return dlopen(name, RTLD_NOW);721}722723static inline void *vkd3d_dlsym(void *handle, const char *symbol)724{725return dlsym(handle, symbol);726}727728static inline int vkd3d_dlclose(void *handle)729{730return dlclose(handle);731}732733static inline const char *vkd3d_dlerror(void)734{735return dlerror();736}737#else738static inline void *vkd3d_dlopen(const char *name)739{740return NULL;741}742743static inline void *vkd3d_dlsym(void *handle, const char *symbol)744{745return NULL;746}747748static inline int vkd3d_dlclose(void *handle)749{750return 0;751}752753static inline const char *vkd3d_dlerror(void)754{755return "Not implemented for this platform.\n";756}757#endif758759#endif /* __VKD3D_COMMON_H */760761762