diff --git a/vrclient_x64/gen_wrapper.py b/vrclient_x64/gen_wrapper.py index 630ce4d9..9e1e1eaf 100755 --- a/vrclient_x64/gen_wrapper.py +++ b/vrclient_x64/gen_wrapper.py @@ -223,6 +223,7 @@ unique_structs = [] UNIX_FUNCS = [ 'vrclient_init', 'vrclient_init_registry', + 'vrclient_get_unix_buffer', 'vrclient_HmdSystemFactory', 'vrclient_VRClientCoreFactory', 'vrclient_unload', diff --git a/vrclient_x64/unix_private.h b/vrclient_x64/unix_private.h index 777d8431..12bd7754 100644 --- a/vrclient_x64/unix_private.h +++ b/vrclient_x64/unix_private.h @@ -30,6 +30,7 @@ extern NTSTATUS vrclient_init_registry( void *args ); extern NTSTATUS vrclient_unload( void *args ); extern NTSTATUS vrclient_HmdSystemFactory( void *args ); extern NTSTATUS vrclient_VRClientCoreFactory( void *args ); +extern NTSTATUS vrclient_get_unix_buffer( void *args ); extern char *vrclient_dos_to_unix_path( const char *src ); extern void vrclient_free_path( char *path ); diff --git a/vrclient_x64/unixlib.cpp b/vrclient_x64/unixlib.cpp index c7aaa196..9b68bd92 100644 --- a/vrclient_x64/unixlib.cpp +++ b/vrclient_x64/unixlib.cpp @@ -2,7 +2,9 @@ #include #include +#include #include +#include #define WINE_VK_HOST #include @@ -370,3 +372,35 @@ NTSTATUS IVRTrackedCamera_IVRTrackedCamera_001_GetVideoStreamFrame( void *args ) *(w_CameraVideoStreamFrame_t_0914 *)params->_ret = *iface->GetVideoStreamFrame( params->nDeviceIndex ); return 0; } + +namespace std +{ +template<> struct hash< struct u_buffer > +{ + using argument_type = struct u_buffer; + using result_type = std::size_t; + result_type operator()( argument_type const& buf ) const { return buf.ptr; } +}; +} + +static pthread_mutex_t buffer_cache_lock = PTHREAD_MUTEX_INITIALIZER; +static std::unordered_map< struct u_buffer, void * > buffer_cache; + +NTSTATUS vrclient_get_unix_buffer( void *args ) +{ + struct vrclient_get_unix_buffer_params *params = (struct vrclient_get_unix_buffer_params *)args; + struct cache_entry *entry; + struct rb_entry *ptr; + + pthread_mutex_lock( &buffer_cache_lock ); + auto iter = buffer_cache.find( params->buf ); + if (iter != buffer_cache.end()) params->ptr = iter->second; + else + { + memcpy( params->ptr, (char *)params->buf, params->buf.len ); + buffer_cache[params->buf] = params->ptr; + } + pthread_mutex_unlock( &buffer_cache_lock ); + + return 0; +} diff --git a/vrclient_x64/unixlib.h b/vrclient_x64/unixlib.h index aa34f712..e0f732ba 100644 --- a/vrclient_x64/unixlib.h +++ b/vrclient_x64/unixlib.h @@ -73,6 +73,12 @@ struct vrclient_VRClientCoreFactory_params int *return_code; }; +struct vrclient_get_unix_buffer_params +{ + struct u_buffer buf; + void *ptr; /* client-side ptr */ +}; + #include #define VRCLIENT_CALL( code, args ) \ diff --git a/vrclient_x64/unixlib_generated.cpp b/vrclient_x64/unixlib_generated.cpp index 0d7823f6..054da882 100644 --- a/vrclient_x64/unixlib_generated.cpp +++ b/vrclient_x64/unixlib_generated.cpp @@ -9,6 +9,7 @@ extern "C" const unixlib_entry_t __wine_unix_call_funcs[] = { vrclient_init, vrclient_init_registry, + vrclient_get_unix_buffer, vrclient_HmdSystemFactory, vrclient_VRClientCoreFactory, vrclient_unload, diff --git a/vrclient_x64/unixlib_generated.h b/vrclient_x64/unixlib_generated.h index 469ca43d..162214b0 100644 --- a/vrclient_x64/unixlib_generated.h +++ b/vrclient_x64/unixlib_generated.h @@ -29223,6 +29223,7 @@ enum unix_funcs { unix_vrclient_init, unix_vrclient_init_registry, + unix_vrclient_get_unix_buffer, unix_vrclient_HmdSystemFactory, unix_vrclient_VRClientCoreFactory, unix_vrclient_unload, diff --git a/vrclient_x64/vrclient_main.c b/vrclient_x64/vrclient_main.c index bd2c248f..f6a4e463 100644 --- a/vrclient_x64/vrclient_main.c +++ b/vrclient_x64/vrclient_main.c @@ -314,6 +314,24 @@ BOOL CDECL vrclient_init_registry(void) return TRUE; } +void *get_unix_buffer( struct u_buffer buf ) +{ + struct vrclient_get_unix_buffer_params params = {.buf = buf}; + void *ret; + + if ((UINT_PTR)buf.ptr == buf.ptr && (UINT_PTR)(buf.ptr + buf.len) == (buf.ptr + buf.len)) + return (void *)(UINT_PTR)buf.ptr; + + if (!(params.ptr = ret = HeapAlloc( GetProcessHeap(), 0, buf.len ))) return NULL; + if (VRCLIENT_CALL( vrclient_get_unix_buffer, ¶ms ) || (ret != params.ptr)) + { + HeapFree( GetProcessHeap(), 0, ret ); + ret = params.ptr; + } + + return ret; +} + static int8_t is_hmd_present_reg(void) { DWORD type, value, wait_status, size; diff --git a/vrclient_x64/vrclient_private.h b/vrclient_x64/vrclient_private.h index 5ef6cdc9..2891a65e 100644 --- a/vrclient_x64/vrclient_private.h +++ b/vrclient_x64/vrclient_private.h @@ -104,6 +104,8 @@ extern void init_rtti( char *base ); struct w_iface *create_win_interface( const char *name, struct u_iface u_iface ); void free_compositor_data_d3d12_device(void); +extern void *get_unix_buffer( struct u_buffer buf ); + struct generic_interface { struct w_iface *object; diff --git a/vrclient_x64/vrclient_structs.h b/vrclient_x64/vrclient_structs.h index 66208699..de038c78 100644 --- a/vrclient_x64/vrclient_structs.h +++ b/vrclient_x64/vrclient_structs.h @@ -134,3 +134,13 @@ struct u_iface template< typename T > operator T*() const { return (T*)(UINT_PTR)this->handle; } #endif /* __cplusplus */ }; + +struct u_buffer +{ + UINT64 ptr; + UINT64 len; +#ifdef __cplusplus + struct u_buffer &operator=(const char* value) { this->ptr = (UINT_PTR)value; this->len = value ? strlen( value ) + 1 : 0; return *this; } + operator char*() const { return (char*)(UINT_PTR)this->ptr; } +#endif /* __cplusplus */ +};