From dd6b7b974e0057da726f71e10c24d057a339605b Mon Sep 17 00:00:00 2001 From: Henrik Gramner Date: Sun, 24 Jan 2016 01:48:18 +0100 Subject: [PATCH] msvs: WinRT support To compile x264 for WinRT the following additional steps has to be performed. * Ensure that the necessary SDK is installed. * Set the correct environment variables in the VS command prompt as shown at https://trac.ffmpeg.org/wiki/CompilationGuide/WinRT * Add one of the following to --extra-cflags depending on the target OS: "-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0A00" (Windows 10) "-DWINAPI_FAMILY=WINAPI_FAMILY_PC_APP -D_WIN32_WINNT=0x0603" (Windows 8.1) --- common/osdep.c | 2 + common/osdep.h | 12 +++-- common/win32thread.c | 124 ++++++++++++++++++++++++++++++------------- common/win32thread.h | 8 +-- configure | 17 +++++- 5 files changed, 118 insertions(+), 45 deletions(-) diff --git a/common/osdep.c b/common/osdep.c index 78359942..074a1f31 100644 --- a/common/osdep.c +++ b/common/osdep.c @@ -126,6 +126,7 @@ int x264_stat( const char *path, x264_struct_stat *buf ) return -1; } +#if !HAVE_WINRT int x264_vfprintf( FILE *stream, const char *format, va_list arg ) { HANDLE console = NULL; @@ -167,3 +168,4 @@ int x264_is_pipe( const char *path ) return 0; } #endif +#endif diff --git a/common/osdep.h b/common/osdep.h index dccbb6bf..995d03c4 100644 --- a/common/osdep.h +++ b/common/osdep.h @@ -79,16 +79,20 @@ int x264_rename( const char *oldname, const char *newname ); #define x264_struct_stat struct _stati64 #define x264_fstat _fstati64 int x264_stat( const char *path, x264_struct_stat *buf ); -int x264_vfprintf( FILE *stream, const char *format, va_list arg ); -int x264_is_pipe( const char *path ); #else #define x264_fopen fopen #define x264_rename rename #define x264_struct_stat struct stat #define x264_fstat fstat #define x264_stat stat -#define x264_vfprintf vfprintf -#define x264_is_pipe(x) 0 +#endif + +#if defined(_WIN32) && !HAVE_WINRT +int x264_vfprintf( FILE *stream, const char *format, va_list arg ); +int x264_is_pipe( const char *path ); +#else +#define x264_vfprintf vfprintf +#define x264_is_pipe(x) 0 #endif #ifdef _MSC_VER diff --git a/common/win32thread.c b/common/win32thread.c index f25e7770..8c439387 100644 --- a/common/win32thread.c +++ b/common/win32thread.c @@ -5,6 +5,7 @@ * * Authors: Steven Walters * Pegasys Inc. + * Henrik Gramner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,32 +32,23 @@ * this API does not detect nor utilize more than 64 cpus for systems that have them. */ #include "common.h" + +#if HAVE_WINRT +/* _beginthreadex() is technically the correct option, but it's only available for Desktop applications. + * Using CreateThread() as an alternative works on Windows Store and Windows Phone 8.1+ as long as we're + * using a dynamically linked MSVCRT which happens to be a requirement for WinRT applications anyway */ +#define _beginthreadex CreateThread +#define InitializeCriticalSectionAndSpinCount(a, b) InitializeCriticalSectionEx(a, b, CRITICAL_SECTION_NO_DEBUG_INFO) +#define WaitForSingleObject(a, b) WaitForSingleObjectEx(a, b, FALSE) +#else #include +#endif /* number of times to spin a thread about to block on a locked mutex before retrying and sleeping if still locked */ #define X264_SPIN_COUNT 0 -/* GROUP_AFFINITY struct */ -typedef struct -{ - ULONG_PTR mask; // KAFFINITY = ULONG_PTR - USHORT group; - USHORT reserved[3]; -} x264_group_affinity_t; - -typedef struct -{ - /* global mutex for replacing MUTEX_INITIALIZER instances */ - x264_pthread_mutex_t static_mutex; - - /* function pointers to conditional variable API on windows 6.0+ kernels */ - void (WINAPI *cond_broadcast)( x264_pthread_cond_t *cond ); - void (WINAPI *cond_init)( x264_pthread_cond_t *cond ); - void (WINAPI *cond_signal)( x264_pthread_cond_t *cond ); - BOOL (WINAPI *cond_wait)( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex, DWORD milliseconds ); -} x264_win32thread_control_t; - -static x264_win32thread_control_t thread_control; +/* global mutex for replacing MUTEX_INITIALIZER instances */ +static x264_pthread_mutex_t static_mutex; /* _beginthreadex requires that the start routine is __stdcall */ static unsigned __stdcall x264_win32thread_worker( void *arg ) @@ -101,9 +93,9 @@ int x264_pthread_mutex_destroy( x264_pthread_mutex_t *mutex ) int x264_pthread_mutex_lock( x264_pthread_mutex_t *mutex ) { - static x264_pthread_mutex_t init = X264_PTHREAD_MUTEX_INITIALIZER; + static const x264_pthread_mutex_t init = X264_PTHREAD_MUTEX_INITIALIZER; if( !memcmp( mutex, &init, sizeof(x264_pthread_mutex_t) ) ) - *mutex = thread_control.static_mutex; + *mutex = static_mutex; EnterCriticalSection( mutex ); return 0; } @@ -114,6 +106,64 @@ int x264_pthread_mutex_unlock( x264_pthread_mutex_t *mutex ) return 0; } +void x264_win32_threading_destroy( void ) +{ + x264_pthread_mutex_destroy( &static_mutex ); + memset( &static_mutex, 0, sizeof(static_mutex) ); +} + +#if HAVE_WINRT +int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condattr_t *attr ) +{ + InitializeConditionVariable( cond ); + return 0; +} + +int x264_pthread_cond_destroy( x264_pthread_cond_t *cond ) +{ + return 0; +} + +int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond ) +{ + WakeAllConditionVariable( cond ); + return 0; +} + +int x264_pthread_cond_signal( x264_pthread_cond_t *cond ) +{ + WakeConditionVariable( cond ); + return 0; +} + +int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex ) +{ + return !SleepConditionVariableCS( cond, mutex, INFINITE ); +} + +int x264_win32_threading_init( void ) +{ + return x264_pthread_mutex_init( &static_mutex, NULL ); +} + +int x264_pthread_num_processors_np( void ) +{ + SYSTEM_INFO si; + GetNativeSystemInfo(&si); + return si.dwNumberOfProcessors; +} + +#else + +static struct +{ + /* function pointers to conditional variable API on windows 6.0+ kernels */ + void (WINAPI *cond_broadcast)( x264_pthread_cond_t *cond ); + void (WINAPI *cond_init)( x264_pthread_cond_t *cond ); + void (WINAPI *cond_signal)( x264_pthread_cond_t *cond ); + BOOL (WINAPI *cond_wait)( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mutex, DWORD milliseconds ); +} thread_control; + /* for pre-Windows 6.0 platforms we need to define and use our own condition variable and api */ typedef struct { @@ -137,7 +187,7 @@ int x264_pthread_cond_init( x264_pthread_cond_t *cond, const x264_pthread_condat x264_win32_cond_t *win32_cond = calloc( 1, sizeof(x264_win32_cond_t) ); if( !win32_cond ) return -1; - cond->ptr = win32_cond; + cond->Ptr = win32_cond; win32_cond->semaphore = CreateSemaphoreW( NULL, 0, 0x7fffffff, NULL ); if( !win32_cond->semaphore ) return -1; @@ -161,7 +211,7 @@ int x264_pthread_cond_destroy( x264_pthread_cond_t *cond ) return 0; /* non native condition variables */ - x264_win32_cond_t *win32_cond = cond->ptr; + x264_win32_cond_t *win32_cond = cond->Ptr; CloseHandle( win32_cond->semaphore ); CloseHandle( win32_cond->waiters_done ); x264_pthread_mutex_destroy( &win32_cond->mtx_broadcast ); @@ -180,7 +230,7 @@ int x264_pthread_cond_broadcast( x264_pthread_cond_t *cond ) } /* non native condition variables */ - x264_win32_cond_t *win32_cond = cond->ptr; + x264_win32_cond_t *win32_cond = cond->Ptr; x264_pthread_mutex_lock( &win32_cond->mtx_broadcast ); x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); int have_waiter = 0; @@ -212,7 +262,7 @@ int x264_pthread_cond_signal( x264_pthread_cond_t *cond ) } /* non-native condition variables */ - x264_win32_cond_t *win32_cond = cond->ptr; + x264_win32_cond_t *win32_cond = cond->Ptr; x264_pthread_mutex_lock( &win32_cond->mtx_broadcast ); x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); @@ -234,7 +284,7 @@ int x264_pthread_cond_wait( x264_pthread_cond_t *cond, x264_pthread_mutex_t *mut return !thread_control.cond_wait( cond, mutex, INFINITE ); /* non native condition variables */ - x264_win32_cond_t *win32_cond = cond->ptr; + x264_win32_cond_t *win32_cond = cond->Ptr; x264_pthread_mutex_lock( &win32_cond->mtx_broadcast ); x264_pthread_mutex_lock( &win32_cond->mtx_waiter_count ); @@ -270,13 +320,7 @@ int x264_win32_threading_init( void ) thread_control.cond_signal = (void*)GetProcAddress( kernel_dll, "WakeConditionVariable" ); thread_control.cond_wait = (void*)GetProcAddress( kernel_dll, "SleepConditionVariableCS" ); } - return x264_pthread_mutex_init( &thread_control.static_mutex, NULL ); -} - -void x264_win32_threading_destroy( void ) -{ - x264_pthread_mutex_destroy( &thread_control.static_mutex ); - memset( &thread_control, 0, sizeof(x264_win32thread_control_t) ); + return x264_pthread_mutex_init( &static_mutex, NULL ); } int x264_pthread_num_processors_np( void ) @@ -289,11 +333,16 @@ int x264_pthread_num_processors_np( void ) #if ARCH_X86_64 /* find function pointers to API functions specific to x86_64 platforms, if they exist */ HANDLE kernel_dll = GetModuleHandleW( L"kernel32.dll" ); - BOOL (*get_thread_affinity)( HANDLE thread, x264_group_affinity_t *group_affinity ) = (void*)GetProcAddress( kernel_dll, "GetThreadGroupAffinity" ); + BOOL (*get_thread_affinity)( HANDLE thread, void *group_affinity ) = (void*)GetProcAddress( kernel_dll, "GetThreadGroupAffinity" ); if( get_thread_affinity ) { /* running on a platform that supports >64 logical cpus */ - x264_group_affinity_t thread_affinity; + struct /* GROUP_AFFINITY */ + { + ULONG_PTR mask; // KAFFINITY = ULONG_PTR + USHORT group; + USHORT reserved[3]; + } thread_affinity; if( get_thread_affinity( GetCurrentThread(), &thread_affinity ) ) process_cpus = thread_affinity.mask; } @@ -305,3 +354,4 @@ int x264_pthread_num_processors_np( void ) return cpus ? cpus : 1; } +#endif diff --git a/common/win32thread.h b/common/win32thread.h index 07cbada8..c16ad001 100644 --- a/common/win32thread.h +++ b/common/win32thread.h @@ -45,12 +45,14 @@ typedef CRITICAL_SECTION x264_pthread_mutex_t; #define X264_PTHREAD_MUTEX_INITIALIZER {0} #define x264_pthread_mutexattr_t int -/* This is the CONDITIONAL_VARIABLE typedef for using Window's native conditional variables on kernels 6.0+. - * MinGW does not currently have this typedef. */ +#if HAVE_WINRT +typedef CONDITION_VARIABLE x264_pthread_cond_t; +#else typedef struct { - void *ptr; + void *Ptr; } x264_pthread_cond_t; +#endif #define x264_pthread_condattr_t int int x264_pthread_create( x264_pthread_t *thread, const x264_pthread_attr_t *attr, diff --git a/configure b/configure index 31f3661f..09643db0 100755 --- a/configure +++ b/configure @@ -373,7 +373,7 @@ NL=" # list of all preprocessor HAVE values we can define CONFIG_HAVE="MALLOC_H ALTIVEC ALTIVEC_H MMX ARMV6 ARMV6T2 NEON BEOSTHREAD POSIXTHREAD WIN32THREAD THREAD LOG2F SWSCALE \ LAVF FFMS GPAC AVS GPL VECTOREXT INTERLACED CPU_COUNT OPENCL THP LSMASH X86_INLINE_ASM AS_FUNC INTEL_DISPATCHER \ - MSA MMAP" + MSA MMAP WINRT" # parse options @@ -768,6 +768,21 @@ if [ $SYS = WINDOWS ]; then if ! rc_check "0 RCDATA {0}" ; then RC="" fi + + if cpp_check "winapifamily.h" "" "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" ; then + [ $compiler = CL ] || die "WinRT requires MSVC" + define HAVE_WINRT + CFLAGS="$CFLAGS -MD" + LDFLAGS="$LDFLAGS -appcontainer" + if ! cpp_check "" "" "defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0603" ; then + die "_WIN32_WINNT must be defined to at least 0x0603 (Windows 8.1) for WinRT" + elif cpp_check "" "" "_WIN32_WINNT >= 0x0A00" ; then + # Universal Windows Platform (Windows 10) + LDFLAGS="$LDFLAGS -lWindowsApp" + fi + cli="no" + opencl="no" + fi fi log_msg "x264 configure script" -- 2.39.2