diff options
author | Jørgen Lind <jorgen.lind@nokia.com> | 2011-03-02 13:26:40 +0100 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2011-03-02 13:46:19 +0100 |
commit | 1691e9ed575bf21121da522acb388f99c4771fc8 (patch) | |
tree | 830fedad558bb531c80ec47cd2e63ec1b9f3a840 /src/3rdparty |
Initial commit for the Qt-Compositor.
The project goal is to be a toolbox which all Qt based Wayland compositors use.
Initial work is done by:
Samuel Rødal <samuel.rodal@nokia.com>
Paul Olav Tvete <paul.tvete@nokia.com>
and myself
Diffstat (limited to 'src/3rdparty')
27 files changed, 6636 insertions, 0 deletions
diff --git a/src/3rdparty/ffi-arm/LICENSE b/src/3rdparty/ffi-arm/LICENSE new file mode 100644 index 000000000..ec2fd6948 --- /dev/null +++ b/src/3rdparty/ffi-arm/LICENSE @@ -0,0 +1,21 @@ +libffi - Copyright (c) 1996-2009 Anthony Green, Red Hat, Inc and others. +See source files for details. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/3rdparty/ffi-arm/ffi.c b/src/3rdparty/ffi-arm/ffi.c new file mode 100644 index 000000000..f6a64758f --- /dev/null +++ b/src/3rdparty/ffi-arm/ffi.c @@ -0,0 +1,309 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 1998, 2008 Red Hat, Inc. + + ARM Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +void ffi_prep_args(char *stack, extended_cif *ecif) +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { + *(void **) argp = ecif->rvalue; + argp += 4; + } + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + (i != 0); + i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if (((*p_arg)->alignment - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, (*p_arg)->alignment); + } + + if ((*p_arg)->type == FFI_TYPE_STRUCT) + argp = (char *) ALIGN(argp, 4); + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + memcpy(argp, *p_argv, (*p_arg)->size); + break; + + default: + FFI_ASSERT(0); + } + } + else if (z == sizeof(int)) + { + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + } + else + { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Round the stack up to a multiple of 8 bytes. This isn't needed + everywhere, but it is on some platforms, and it doesn't harm anything + when it isn't needed. */ + cif->bytes = (cif->bytes + 7) & ~7; + + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + cif->flags = (unsigned) cif->rtype->type; + break; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags = (unsigned) FFI_TYPE_SINT64; + break; + + case FFI_TYPE_STRUCT: + if (cif->rtype->size <= 4) + /* A Composite Type not larger than 4 bytes is returned in r0. */ + cif->flags = (unsigned)FFI_TYPE_INT; + else + /* A Composite Type larger than 4 bytes, or whose size cannot + be determined statically ... is stored in memory at an + address passed [in r0]. */ + cif->flags = (unsigned)FFI_TYPE_STRUCT; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, + unsigned, unsigned, unsigned *, void (*fn)(void)); + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + extended_cif ecif; + + int small_struct = (cif->flags == FFI_TYPE_INT + && cif->rtype->type == FFI_TYPE_STRUCT); + + ecif.cif = cif; + ecif.avalue = avalue; + + unsigned int temp; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (cif->flags == FFI_TYPE_STRUCT)) + { + ecif.rvalue = alloca(cif->rtype->size); + } + else if (small_struct) + ecif.rvalue = &temp; + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue, + fn); + + break; + default: + FFI_ASSERT(0); + break; + } + if (small_struct) + memcpy (rvalue, &temp, cif->rtype->size); +} + +/** private members **/ + +static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, + void** args, ffi_cif* cif); + +void ffi_closure_SYSV (ffi_closure *); + +/* This function is jumped to by the trampoline */ + +unsigned int +ffi_closure_SYSV_inner (closure, respp, args) + ffi_closure *closure; + void **respp; + void *args; +{ + // our various things... + ffi_cif *cif; + void **arg_area; + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void*)); + + /* this call will initialize ARG_AREA, such that each + * element in that array points to the corresponding + * value on the stack; and if the function returns + * a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); + + (closure->fun) (cif, *respp, arg_area, closure->user_data); + + return cif->flags; +} + +/*@-exportheader@*/ +static void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( cif->flags == FFI_TYPE_STRUCT ) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + + size_t alignment = (*p_arg)->alignment; + if (alignment < 4) + alignment = 4; + /* Align if necessary */ + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) ALIGN(argp, alignment); + } + + z = (*p_arg)->size; + + /* because we're little endian, this is what it turns into. */ + + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + +/* How to make a trampoline. */ + +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */ \ + *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */ \ + *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */ \ + *(unsigned int*) &__tramp[12] = __ctx; \ + *(unsigned int*) &__tramp[16] = __fun; \ + __clear_cache((&__tramp[0]), (&__tramp[19])); \ + }) + + +/* the cif must already be prep'ed */ + +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + FFI_ASSERT (cif->abi == FFI_SYSV); + + FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ + &ffi_closure_SYSV, \ + codeloc); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} diff --git a/src/3rdparty/ffi-arm/ffi.h b/src/3rdparty/ffi-arm/ffi.h new file mode 100644 index 000000000..1f578d9a6 --- /dev/null +++ b/src/3rdparty/ffi-arm/ffi.h @@ -0,0 +1,399 @@ +/* -----------------------------------------------------------------*-C-*- + libffi 3.0.9 - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------- + The basic API is described in the README file. + + The raw API is designed to bypass some of the argument packing + and unpacking on architectures for which it can be avoided. + + The closure API allows interpreted functions to be packaged up + inside a C function pointer, so that they can be called as C functions, + with no understanding on the client side that they are interpreted. + It can also be used in other cases in which it is necessary to package + up a user specified parameter and a function pointer as a single + function pointer. + + The closure API must be implemented in order to get its functionality, + e.g. for use by gij. Routines are provided to emulate the raw API + if the underlying platform doesn't allow faster implementation. + + More details on the raw and cloure API can be found in: + + http://gcc.gnu.org/ml/java/1999-q3/msg00138.html + + and + + http://gcc.gnu.org/ml/java/1999-q3/msg00174.html + -------------------------------------------------------------------- */ + +#ifndef LIBFFI_H +#define LIBFFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Specify which architecture libffi is configured for. */ +#define ARM + +/* ---- System configuration information --------------------------------- */ + +#include <ffitarget.h> + +#ifndef LIBFFI_ASM + +#ifdef _MSC_VER +#define __attribute__(X) +#endif + +#include <stddef.h> +#include <limits.h> + +/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). + But we can find it either under the correct ANSI name, or under GNU + C's internal name. */ +#ifdef LONG_LONG_MAX +# define FFI_LONG_LONG_MAX LONG_LONG_MAX +#else +# ifdef LLONG_MAX +# define FFI_LONG_LONG_MAX LLONG_MAX +# else +# ifdef __GNUC__ +# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ +# endif +# endif +#endif + +/* The closure code assumes that this works on pointers, i.e. a size_t */ +/* can hold a pointer. */ + +typedef struct _ffi_type +{ + size_t size; + unsigned short alignment; + unsigned short type; + struct _ffi_type **elements; +} ffi_type; + +#ifndef LIBFFI_HIDE_BASIC_TYPES +#if SCHAR_MAX == 127 +# define ffi_type_uchar ffi_type_uint8 +# define ffi_type_schar ffi_type_sint8 +#else + #error "char size not supported" +#endif + +#if SHRT_MAX == 32767 +# define ffi_type_ushort ffi_type_uint16 +# define ffi_type_sshort ffi_type_sint16 +#elif SHRT_MAX == 2147483647 +# define ffi_type_ushort ffi_type_uint32 +# define ffi_type_sshort ffi_type_sint32 +#else + #error "short size not supported" +#endif + +#if INT_MAX == 32767 +# define ffi_type_uint ffi_type_uint16 +# define ffi_type_sint ffi_type_sint16 +#elif INT_MAX == 2147483647 +# define ffi_type_uint ffi_type_uint32 +# define ffi_type_sint ffi_type_sint32 +#elif INT_MAX == 9223372036854775807 +# define ffi_type_uint ffi_type_uint64 +# define ffi_type_sint ffi_type_sint64 +#else + #error "int size not supported" +#endif + +#if LONG_MAX == 2147483647 +# if FFI_LONG_LONG_MAX != 9223372036854775807 + #error "no 64-bit data type supported" +# endif +#elif LONG_MAX != 9223372036854775807 + #error "long size not supported" +#endif + +#if LONG_MAX == 2147483647 +# define ffi_type_ulong ffi_type_uint32 +# define ffi_type_slong ffi_type_sint32 +#elif LONG_MAX == 9223372036854775807 +# define ffi_type_ulong ffi_type_uint64 +# define ffi_type_slong ffi_type_sint64 +#else + #error "long size not supported" +#endif + +/* These are defined in types.c */ +extern ffi_type ffi_type_void; +extern ffi_type ffi_type_uint8; +extern ffi_type ffi_type_sint8; +extern ffi_type ffi_type_uint16; +extern ffi_type ffi_type_sint16; +extern ffi_type ffi_type_uint32; +extern ffi_type ffi_type_sint32; +extern ffi_type ffi_type_uint64; +extern ffi_type ffi_type_sint64; +extern ffi_type ffi_type_float; +extern ffi_type ffi_type_double; +extern ffi_type ffi_type_pointer; + +#if 1 +extern ffi_type ffi_type_longdouble; +#else +#define ffi_type_longdouble ffi_type_double +#endif +#endif /* LIBFFI_HIDE_BASIC_TYPES */ + +typedef enum { + FFI_OK = 0, + FFI_BAD_TYPEDEF, + FFI_BAD_ABI +} ffi_status; + +typedef unsigned FFI_TYPE; + +typedef struct { + ffi_abi abi; + unsigned nargs; + ffi_type **arg_types; + ffi_type *rtype; + unsigned bytes; + unsigned flags; +#ifdef FFI_EXTRA_CIF_FIELDS + FFI_EXTRA_CIF_FIELDS; +#endif +} ffi_cif; + +/* ---- Definitions for the raw API -------------------------------------- */ + +#ifndef FFI_SIZEOF_ARG +# if LONG_MAX == 2147483647 +# define FFI_SIZEOF_ARG 4 +# elif LONG_MAX == 9223372036854775807 +# define FFI_SIZEOF_ARG 8 +# endif +#endif + +#ifndef FFI_SIZEOF_JAVA_RAW +# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG +#endif + +typedef union { + ffi_sarg sint; + ffi_arg uint; + float flt; + char data[FFI_SIZEOF_ARG]; + void* ptr; +} ffi_raw; + +#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 +/* This is a special case for mips64/n32 ABI (and perhaps others) where + sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ +typedef union { + signed int sint; + unsigned int uint; + float flt; + char data[FFI_SIZEOF_JAVA_RAW]; + void* ptr; +} ffi_java_raw; +#else +typedef ffi_raw ffi_java_raw; +#endif + + +void ffi_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_raw *avalue); + +void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +size_t ffi_raw_size (ffi_cif *cif); + +/* This is analogous to the raw API, except it uses Java parameter */ +/* packing, even on 64-bit machines. I.e. on 64-bit machines */ +/* longs and doubles are followed by an empty 64-bit word. */ + +void ffi_java_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_java_raw *avalue); + +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); +size_t ffi_java_raw_size (ffi_cif *cif); + +/* ---- Definitions for closures ----------------------------------------- */ + +#if FFI_CLOSURES + +typedef struct { + char tramp[FFI_TRAMPOLINE_SIZE]; + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); + void *user_data; +#ifdef __GNUC__ +} ffi_closure __attribute__((aligned (8))); +#else +} ffi_closure; +#endif + +void *ffi_closure_alloc (size_t size, void **code); +void ffi_closure_free (void *); + +ffi_status +ffi_prep_closure (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data); + +ffi_status +ffi_prep_closure_loc (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void*codeloc); + +typedef struct { + char tramp[FFI_TRAMPOLINE_SIZE]; + + ffi_cif *cif; + +#if !FFI_NATIVE_RAW_API + + /* if this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. */ + + void (*translate_args)(ffi_cif*,void*,void**,void*); + void *this_closure; + +#endif + + void (*fun)(ffi_cif*,void*,ffi_raw*,void*); + void *user_data; + +} ffi_raw_closure; + +typedef struct { + char tramp[FFI_TRAMPOLINE_SIZE]; + + ffi_cif *cif; + +#if !FFI_NATIVE_RAW_API + + /* if this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. */ + + void (*translate_args)(ffi_cif*,void*,void**,void*); + void *this_closure; + +#endif + + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); + void *user_data; + +} ffi_java_raw_closure; + +ffi_status +ffi_prep_raw_closure (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data); + +ffi_status +ffi_prep_raw_closure_loc (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data, + void *codeloc); + +ffi_status +ffi_prep_java_raw_closure (ffi_java_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void *user_data); + +ffi_status +ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void *user_data, + void *codeloc); + +#endif /* FFI_CLOSURES */ + +/* ---- Public interface definition -------------------------------------- */ + +ffi_status ffi_prep_cif(ffi_cif *cif, + ffi_abi abi, + unsigned int nargs, + ffi_type *rtype, + ffi_type **atypes); + +void ffi_call(ffi_cif *cif, + void (*fn)(void), + void *rvalue, + void **avalue); + +/* Useful for eliminating compiler warnings */ +#define FFI_FN(f) ((void (*)(void))f) + +/* ---- Definitions shared with assembly code ---------------------------- */ + +#endif + +/* If these change, update src/mips/ffitarget.h. */ +#define FFI_TYPE_VOID 0 +#define FFI_TYPE_INT 1 +#define FFI_TYPE_FLOAT 2 +#define FFI_TYPE_DOUBLE 3 +#if 1 +#define FFI_TYPE_LONGDOUBLE 4 +#else +#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE +#endif +#define FFI_TYPE_UINT8 5 +#define FFI_TYPE_SINT8 6 +#define FFI_TYPE_UINT16 7 +#define FFI_TYPE_SINT16 8 +#define FFI_TYPE_UINT32 9 +#define FFI_TYPE_SINT32 10 +#define FFI_TYPE_UINT64 11 +#define FFI_TYPE_SINT64 12 +#define FFI_TYPE_STRUCT 13 +#define FFI_TYPE_POINTER 14 + +/* This should always refer to the last type code (for sanity checks) */ +#define FFI_TYPE_LAST FFI_TYPE_POINTER + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/ffi-arm/ffi.pro b/src/3rdparty/ffi-arm/ffi.pro new file mode 100644 index 000000000..1e9106292 --- /dev/null +++ b/src/3rdparty/ffi-arm/ffi.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +TARGET = ffi +DESTDIR=$$PWD/../../../lib/ + +CONFIG -= qt +CONFIG += shared + +SOURCES = ffi.c \ + prep_cif.c \ + types.c \ + sysv.S + +OBJECTS_DIR = .obj diff --git a/src/3rdparty/ffi-arm/ffi_common.h b/src/3rdparty/ffi-arm/ffi_common.h new file mode 100644 index 000000000..42cace915 --- /dev/null +++ b/src/3rdparty/ffi-arm/ffi_common.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------- + ffi_common.h - Copyright (c) 1996 Red Hat, Inc. + Copyright (C) 2007 Free Software Foundation, Inc + + Common internal definitions and macros. Only necessary for building + libffi. + ----------------------------------------------------------------------- */ + +#ifndef FFI_COMMON_H +#define FFI_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <fficonfig.h> + +/* Do not move this. Some versions of AIX are very picky about where + this is positioned. */ +#ifdef __GNUC__ +/* mingw64 defines this already in malloc.h. */ +#ifndef alloca +# define alloca __builtin_alloca +#endif +# define MAYBE_UNUSED __attribute__((__unused__)) +#else +# define MAYBE_UNUSED +# if HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +# ifdef _MSC_VER +# define alloca _alloca +# else +char *alloca (); +# endif +# endif +# endif +# endif +#endif + +/* Check for the existence of memcpy. */ +#if STDC_HEADERS +# include <string.h> +#else +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(FFI_DEBUG) +#include <stdio.h> +#endif + +#ifdef FFI_DEBUG +void ffi_assert(char *expr, char *file, int line); +void ffi_stop_here(void); +void ffi_type_test(ffi_type *a, char *file, int line); + +#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) +#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) +#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__) +#else +#define FFI_ASSERT(x) +#define FFI_ASSERT_AT(x, f, l) +#define FFI_ASSERT_VALID_TYPE(x) +#endif + +#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) +#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a) + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif); + +/* Extended cif, used in callback from assembly routine */ +typedef struct +{ + ffi_cif *cif; + void *rvalue; + void **avalue; +} extended_cif; + +/* Terse sized type definitions. */ +#if defined(_MSC_VER) || defined(__sgi) +typedef unsigned char UINT8; +typedef signed char SINT8; +typedef unsigned short UINT16; +typedef signed short SINT16; +typedef unsigned int UINT32; +typedef signed int SINT32; +# ifdef _MSC_VER +typedef unsigned __int64 UINT64; +typedef signed __int64 SINT64; +# else +# include <inttypes.h> +typedef uint64_t UINT64; +typedef int64_t SINT64; +# endif +#else +typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); +typedef signed int SINT8 __attribute__((__mode__(__QI__))); +typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); +typedef signed int SINT16 __attribute__((__mode__(__HI__))); +typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); +typedef signed int SINT32 __attribute__((__mode__(__SI__))); +typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); +typedef signed int SINT64 __attribute__((__mode__(__DI__))); +#endif + +typedef float FLOAT32; + + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/src/3rdparty/ffi-arm/fficonfig.h b/src/3rdparty/ffi-arm/fficonfig.h new file mode 100644 index 000000000..61b3a1db6 --- /dev/null +++ b/src/3rdparty/ffi-arm/fficonfig.h @@ -0,0 +1,182 @@ +/* fficonfig.h. Generated from fficonfig.h.in by configure. */ +/* fficonfig.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to the flags needed for the .section .eh_frame directive. */ +#define EH_FRAME_FLAGS "a" + +/* Define this if you want extra debugging. */ +/* #undef FFI_DEBUG */ + +/* Cannot use malloc on this target, so, we revert to alternative means */ +/* #undef FFI_MMAP_EXEC_WRIT */ + +/* Define this is you do not want support for the raw API. */ +/* #undef FFI_NO_RAW_API */ + +/* Define this is you do not want support for aggregate types. */ +/* #undef FFI_NO_STRUCTS */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define if your assembler supports .cfi_* directives. */ +#define HAVE_AS_CFI_PSEUDO_OP 1 + +/* Define if your assembler supports .register. */ +/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ + +/* Define if your assembler and linker support unaligned PC relative relocs. + */ +/* #undef HAVE_AS_SPARC_UA_PCREL */ + +/* Define if your assembler supports PC relative relocs. */ +/* #undef HAVE_AS_X86_PCREL */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if __attribute__((visibility("hidden"))) is supported. */ +#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the long double type and it is bigger than a double */ +#define HAVE_LONG_DOUBLE 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define if mmap with MAP_ANON(YMOUS) works. */ +#define HAVE_MMAP_ANON 1 + +/* Define if mmap of /dev/zero works. */ +#define HAVE_MMAP_DEV_ZERO 1 + +/* Define if read-only mmap of a plain file works. */ +#define HAVE_MMAP_FILE 1 + +/* Define if .eh_frame sections should be read-only. */ +#define HAVE_RO_EH_FRAME 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the <sys/mman.h> header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libffi" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libffi" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libffi 3.0.9" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libffi" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.0.9" + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 12 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define this if you are using Purify and want to suppress spurious messages. + */ +/* #undef USING_PURIFY */ + +/* Version number of package */ +#define VERSION "3.0.9" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + + +#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE +#ifdef LIBFFI_ASM +#define FFI_HIDDEN(name) .hidden name +#else +#define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) +#endif +#else +#ifdef LIBFFI_ASM +#define FFI_HIDDEN(name) +#else +#define FFI_HIDDEN +#endif +#endif + diff --git a/src/3rdparty/ffi-arm/ffitarget.h b/src/3rdparty/ffi-arm/ffitarget.h new file mode 100644 index 000000000..a95742669 --- /dev/null +++ b/src/3rdparty/ffi-arm/ffitarget.h @@ -0,0 +1,49 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. + Target configuration macros for ARM. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 +} ffi_abi; +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 20 +#define FFI_NATIVE_RAW_API 0 + +#endif + diff --git a/src/3rdparty/ffi-arm/prep_cif.c b/src/3rdparty/ffi-arm/prep_cif.c new file mode 100644 index 000000000..eb78f9a2e --- /dev/null +++ b/src/3rdparty/ffi-arm/prep_cif.c @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------- + prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include <ffi.h> +#include <ffi_common.h> +#include <stdlib.h> + +/* Round up to FFI_SIZEOF_ARG. */ + +#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) + +/* Perform machine independent initialization of aggregate type + specifications. */ + +static ffi_status initialize_aggregate(ffi_type *arg) +{ + ffi_type **ptr; + + FFI_ASSERT(arg != NULL); + + FFI_ASSERT(arg->elements != NULL); + FFI_ASSERT(arg->size == 0); + FFI_ASSERT(arg->alignment == 0); + + ptr = &(arg->elements[0]); + + while ((*ptr) != NULL) + { + if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + return FFI_BAD_TYPEDEF; + + /* Perform a sanity check on the argument type */ + FFI_ASSERT_VALID_TYPE(*ptr); + + arg->size = ALIGN(arg->size, (*ptr)->alignment); + arg->size += (*ptr)->size; + + arg->alignment = (arg->alignment > (*ptr)->alignment) ? + arg->alignment : (*ptr)->alignment; + + ptr++; + } + + /* Structure size includes tail padding. This is important for + structures that fit in one register on ABIs like the PowerPC64 + Linux ABI that right justify small structs in a register. + It's also needed for nested structure layout, for example + struct A { long a; char b; }; struct B { struct A x; char y; }; + should find y at an offset of 2*sizeof(long) and result in a + total size of 3*sizeof(long). */ + arg->size = ALIGN (arg->size, arg->alignment); + + if (arg->size == 0) + return FFI_BAD_TYPEDEF; + else + return FFI_OK; +} + +#ifndef __CRIS__ +/* The CRIS ABI specifies structure elements to have byte + alignment only, so it completely overrides this functions, + which assumes "natural" alignment and padding. */ + +/* Perform machine independent ffi_cif preparation, then call + machine dependent routine. */ + +ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, + ffi_type *rtype, ffi_type **atypes) +{ + unsigned bytes = 0; + unsigned int i; + ffi_type **ptr; + + FFI_ASSERT(cif != NULL); + FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); + + cif->abi = abi; + cif->arg_types = atypes; + cif->nargs = nargs; + cif->rtype = rtype; + + cif->flags = 0; + + /* Initialize the return type if necessary */ + if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) + return FFI_BAD_TYPEDEF; + + /* Perform a sanity check on the return type */ + FFI_ASSERT_VALID_TYPE(cif->rtype); + + /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ +#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA + /* Make space for the return structure pointer */ + if (cif->rtype->type == FFI_TYPE_STRUCT +#ifdef SPARC + && (cif->abi != FFI_V9 || cif->rtype->size > 32) +#endif +#ifdef X86_DARWIN + && (cif->rtype->size > 8) +#endif + ) + bytes = STACK_ARG_SIZE(sizeof(void*)); +#endif + + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + { + + /* Initialize any uninitialized aggregate type definitions */ + if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + return FFI_BAD_TYPEDEF; + + /* Perform a sanity check on the argument type, do this + check after the initialization. */ + FFI_ASSERT_VALID_TYPE(*ptr); + +#if !defined __x86_64__ && !defined S390 && !defined PA +#ifdef SPARC + if (((*ptr)->type == FFI_TYPE_STRUCT + && ((*ptr)->size > 16 || cif->abi != FFI_V9)) + || ((*ptr)->type == FFI_TYPE_LONGDOUBLE + && cif->abi != FFI_V9)) + bytes += sizeof(void*); + else +#endif + { + /* Add any padding if necessary */ + if (((*ptr)->alignment - 1) & bytes) + bytes = ALIGN(bytes, (*ptr)->alignment); + + bytes += STACK_ARG_SIZE((*ptr)->size); + } +#endif + } + + cif->bytes = bytes; + + /* Perform machine dependent cif processing */ + return ffi_prep_cif_machdep(cif); +} +#endif /* not __CRIS__ */ + +#if FFI_CLOSURES + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data) +{ + return ffi_prep_closure_loc (closure, cif, fun, user_data, closure); +} + +#endif diff --git a/src/3rdparty/ffi-arm/sysv.S b/src/3rdparty/ffi-arm/sysv.S new file mode 100644 index 000000000..4c289c697 --- /dev/null +++ b/src/3rdparty/ffi-arm/sysv.S @@ -0,0 +1,306 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc. + + ARM Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include <fficonfig.h> +#include <ffi.h> +#ifdef HAVE_MACHINE_ASM_H +#include <machine/asm.h> +#else +#ifdef __USER_LABEL_PREFIX__ +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +/* Use the right prefix for global labels. */ +#define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x) +#else +#define CNAME(x) x +#endif +#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): +#endif + +#ifdef __ELF__ +#define LSYM(x) .x +#else +#define LSYM(x) x +#endif + +/* We need a better way of testing for this, but for now, this is all + we can do. */ +@ This selects the minimum architecture level required. +#define __ARM_ARCH__ 3 + +#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 4 +#endif + +#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 5 +#endif + +#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_6M__) +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 6 +#endif + +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) +# undef __ARM_ARCH__ +# define __ARM_ARCH__ 7 +#endif + +#if __ARM_ARCH__ >= 5 +# define call_reg(x) blx x +#elif defined (__ARM_ARCH_4T__) +# define call_reg(x) mov lr, pc ; bx x +# if defined(__thumb__) || defined(__THUMB_INTERWORK__) +# define __INTERWORKING__ +# endif +#else +# define call_reg(x) mov lr, pc ; mov pc, x +#endif + +/* Conditionally compile unwinder directives. */ +#ifdef __ARM_EABI__ +#define UNWIND +#else +#define UNWIND @ +#endif + + +#if defined(__thumb__) && !defined(__THUMB_INTERWORK__) +.macro ARM_FUNC_START name + .text + .align 0 + .thumb + .thumb_func + ENTRY(\name) + bx pc + nop + .arm + UNWIND .fnstart +/* A hook to tell gdb that we've switched to ARM mode. Also used to call + directly from other local arm routines. */ +_L__\name: +.endm +#else +.macro ARM_FUNC_START name + .text + .align 0 + .arm + ENTRY(\name) + UNWIND .fnstart +.endm +#endif + +.macro RETLDM regs=, cond=, dirn=ia +#if defined (__INTERWORKING__) + .ifc "\regs","" + ldr\cond lr, [sp], #4 + .else + ldm\cond\dirn sp!, {\regs, lr} + .endif + bx\cond lr +#else + .ifc "\regs","" + ldr\cond pc, [sp], #4 + .else + ldm\cond\dirn sp!, {\regs, pc} + .endif +#endif +.endm + + + @ r0: ffi_prep_args + @ r1: &ecif + @ r2: cif->bytes + @ r3: fig->flags + @ sp+0: ecif.rvalue + @ sp+4: fn + + @ This assumes we are using gas. +ARM_FUNC_START ffi_call_SYSV + @ Save registers + stmfd sp!, {r0-r3, fp, lr} + UNWIND .save {r0-r3, fp, lr} + mov fp, sp + + UNWIND .setfp fp, sp + + @ Make room for all of the new args. + sub sp, fp, r2 + + @ Place all of the ffi_prep_args in position + mov ip, r0 + mov r0, sp + @ r1 already set + + @ Call ffi_prep_args(stack, &ecif) + call_reg(ip) + + @ move first 4 parameters in registers + ldmia sp, {r0-r3} + + @ and adjust stack + ldr ip, [fp, #8] + cmp ip, #16 + movhs ip, #16 + add sp, sp, ip + + @ call (fn) (...) + ldr ip, [fp, #28] + call_reg(ip) + + @ Remove the space we pushed for the args + mov sp, fp + + @ Load r2 with the pointer to storage for the return value + ldr r2, [sp, #24] + + @ Load r3 with the return type code + ldr r3, [sp, #12] + + @ If the return value pointer is NULL, assume no return value. + cmp r2, #0 + beq LSYM(Lepilogue) + +@ return INT + cmp r3, #FFI_TYPE_INT +#if defined(__SOFTFP__) || defined(__ARM_EABI__) + cmpne r3, #FFI_TYPE_FLOAT +#endif + streq r0, [r2] + beq LSYM(Lepilogue) + + @ return INT64 + cmp r3, #FFI_TYPE_SINT64 +#if defined(__SOFTFP__) || defined(__ARM_EABI__) + cmpne r3, #FFI_TYPE_DOUBLE +#endif + stmeqia r2, {r0, r1} + +#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) + beq LSYM(Lepilogue) + +@ return FLOAT + cmp r3, #FFI_TYPE_FLOAT + stfeqs f0, [r2] + beq LSYM(Lepilogue) + +@ return DOUBLE or LONGDOUBLE + cmp r3, #FFI_TYPE_DOUBLE + stfeqd f0, [r2] +#endif + +LSYM(Lepilogue): + RETLDM "r0-r3,fp" + +.ffi_call_SYSV_end: + UNWIND .fnend + .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) + +/* + unsigned int FFI_HIDDEN + ffi_closure_SYSV_inner (closure, respp, args) + ffi_closure *closure; + void **respp; + void *args; +*/ + +ARM_FUNC_START ffi_closure_SYSV + UNWIND .pad #16 + add ip, sp, #16 + stmfd sp!, {ip, lr} + UNWIND .save {r0, lr} + add r2, sp, #8 + .pad #16 + sub sp, sp, #16 + str sp, [sp, #8] + add r1, sp, #8 + bl ffi_closure_SYSV_inner + cmp r0, #FFI_TYPE_INT + beq .Lretint + + cmp r0, #FFI_TYPE_FLOAT +#if defined(__SOFTFP__) || defined(__ARM_EABI__) + beq .Lretint +#else + beq .Lretfloat +#endif + + cmp r0, #FFI_TYPE_DOUBLE +#if defined(__SOFTFP__) || defined(__ARM_EABI__) + beq .Lretlonglong +#else + beq .Lretdouble +#endif + + cmp r0, #FFI_TYPE_LONGDOUBLE +#if defined(__SOFTFP__) || defined(__ARM_EABI__) + beq .Lretlonglong +#else + beq .Lretlongdouble +#endif + + cmp r0, #FFI_TYPE_SINT64 + beq .Lretlonglong +.Lclosure_epilogue: + add sp, sp, #16 + ldmfd sp, {sp, pc} +.Lretint: + ldr r0, [sp] + b .Lclosure_epilogue +.Lretlonglong: + ldr r0, [sp] + ldr r1, [sp, #4] + b .Lclosure_epilogue + +#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) +.Lretfloat: + ldfs f0, [sp] + b .Lclosure_epilogue +.Lretdouble: + ldfd f0, [sp] + b .Lclosure_epilogue +.Lretlongdouble: + ldfd f0, [sp] + b .Lclosure_epilogue +#endif + +.ffi_closure_SYSV_end: + UNWIND .fnend + .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",%progbits +#endif diff --git a/src/3rdparty/ffi-arm/types.c b/src/3rdparty/ffi-arm/types.c new file mode 100644 index 000000000..0a11eb0fb --- /dev/null +++ b/src/3rdparty/ffi-arm/types.c @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------- + types.c - Copyright (c) 1996, 1998 Red Hat, Inc. + + Predefined ffi_types needed by libffi. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +/* Hide the basic type definitions from the header file, so that we + can redefine them here as "const". */ +#define LIBFFI_HIDE_BASIC_TYPES + +#include <ffi.h> +#include <ffi_common.h> + +/* Type definitions */ + +#define FFI_TYPEDEF(name, type, id) \ +struct struct_align_##name { \ + char c; \ + type x; \ +}; \ +const ffi_type ffi_type_##name = { \ + sizeof(type), \ + offsetof(struct struct_align_##name, x), \ + id, NULL \ +} + +/* Size and alignment are fake here. They must not be 0. */ +const ffi_type ffi_type_void = { + 1, 1, FFI_TYPE_VOID, NULL +}; + +FFI_TYPEDEF(uint8, UINT8, FFI_TYPE_UINT8); +FFI_TYPEDEF(sint8, SINT8, FFI_TYPE_SINT8); +FFI_TYPEDEF(uint16, UINT16, FFI_TYPE_UINT16); +FFI_TYPEDEF(sint16, SINT16, FFI_TYPE_SINT16); +FFI_TYPEDEF(uint32, UINT32, FFI_TYPE_UINT32); +FFI_TYPEDEF(sint32, SINT32, FFI_TYPE_SINT32); +FFI_TYPEDEF(uint64, UINT64, FFI_TYPE_UINT64); +FFI_TYPEDEF(sint64, SINT64, FFI_TYPE_SINT64); + +FFI_TYPEDEF(pointer, void*, FFI_TYPE_POINTER); + +FFI_TYPEDEF(float, float, FFI_TYPE_FLOAT); +FFI_TYPEDEF(double, double, FFI_TYPE_DOUBLE); + +#ifdef __alpha__ +/* Even if we're not configured to default to 128-bit long double, + maintain binary compatibility, as -mlong-double-128 can be used + at any time. */ +/* Validate the hard-coded number below. */ +# if defined(__LONG_DOUBLE_128__) && FFI_TYPE_LONGDOUBLE != 4 +# error FFI_TYPE_LONGDOUBLE out of date +# endif +const ffi_type ffi_type_longdouble = { 16, 16, 4, NULL }; +#elif FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE +FFI_TYPEDEF(longdouble, long double, FFI_TYPE_LONGDOUBLE); +#endif diff --git a/src/3rdparty/wayland/client/client.pro b/src/3rdparty/wayland/client/client.pro new file mode 100644 index 000000000..ebf24b4ee --- /dev/null +++ b/src/3rdparty/wayland/client/client.pro @@ -0,0 +1,19 @@ +TEMPLATE = lib +TARGET = wayland-client +DESTDIR=$$PWD/../../../../lib/ + +CONFIG -= qt +CONFIG += shared + +INCLUDEPATH += $$PWD/.. \ + $$PWD/../../ffi + +LIBS += -L $$PWD/../../../../lib/ -lffi + +SOURCES = ../wayland-client.c \ + ../wayland-protocol.c \ + ../connection.c \ + ../wayland-util.c \ + ../wayland-hash.c + +OBJECTS_DIR = .obj diff --git a/src/3rdparty/wayland/connection.c b/src/3rdparty/wayland/connection.c new file mode 100644 index 000000000..4a004705b --- /dev/null +++ b/src/3rdparty/wayland/connection.c @@ -0,0 +1,729 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/uio.h> +#include <ffi.h> +#include <assert.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "wayland-util.h" +#include "connection.h" + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +struct wl_buffer { + char data[4096]; + int head, tail; +}; + +#define MASK(i) ((i) & 4095) + +struct wl_closure { + int count; + const struct wl_message *message; + ffi_type *types[20]; + ffi_cif cif; + void *args[20]; + uint32_t buffer[64]; + uint32_t *start; +}; + +struct wl_connection { + struct wl_buffer in, out; + struct wl_buffer fds_in, fds_out; + int fd; + void *data; + wl_connection_update_func_t update; + struct wl_closure receive_closure, send_closure; +}; + +union wl_value { + uint32_t uint32; + char *string; + struct wl_object *object; + uint32_t new_id; + struct wl_array *array; +}; + +static void +wl_buffer_put(struct wl_buffer *b, const void *data, size_t count) +{ + int head, size; + + head = MASK(b->head); + if (head + count <= sizeof b->data) { + memcpy(b->data + head, data, count); + } else { + size = sizeof b->data - head; + memcpy(b->data + head, data, size); + memcpy(b->data, (const char *) data + size, count - size); + } + + b->head += count; +} + +static void +wl_buffer_put_iov(struct wl_buffer *b, struct iovec *iov, int *count) +{ + int head, tail; + + head = MASK(b->head); + tail = MASK(b->tail); + if (head < tail) { + iov[0].iov_base = b->data + head; + iov[0].iov_len = tail - head; + *count = 1; + } else if (tail == 0) { + iov[0].iov_base = b->data + head; + iov[0].iov_len = sizeof b->data - head; + *count = 1; + } else { + iov[0].iov_base = b->data + head; + iov[0].iov_len = sizeof b->data - head; + iov[1].iov_base = b->data; + iov[1].iov_len = tail; + *count = 2; + } +} + +static void +wl_buffer_get_iov(struct wl_buffer *b, struct iovec *iov, int *count) +{ + int head, tail; + + head = MASK(b->head); + tail = MASK(b->tail); + if (tail < head) { + iov[0].iov_base = b->data + tail; + iov[0].iov_len = head - tail; + *count = 1; + } else if (head == 0) { + iov[0].iov_base = b->data + tail; + iov[0].iov_len = sizeof b->data - tail; + *count = 1; + } else { + iov[0].iov_base = b->data + tail; + iov[0].iov_len = sizeof b->data - tail; + iov[1].iov_base = b->data; + iov[1].iov_len = head; + *count = 2; + } +} + +static void +wl_buffer_copy(struct wl_buffer *b, void *data, size_t count) +{ + int tail, size; + + tail = MASK(b->tail); + if (tail + count <= sizeof b->data) { + memcpy(data, b->data + tail, count); + } else { + size = sizeof b->data - tail; + memcpy(data, b->data + tail, size); + memcpy((char *) data + size, b->data, count - size); + } +} + +struct wl_connection * +wl_connection_create(int fd, + wl_connection_update_func_t update, + void *data) +{ + struct wl_connection *connection; + + connection = malloc(sizeof *connection); + memset(connection, 0, sizeof *connection); + connection->fd = fd; + connection->update = update; + connection->data = data; + + connection->update(connection, + WL_CONNECTION_READABLE, + connection->data); + + return connection; +} + +void +wl_connection_destroy(struct wl_connection *connection) +{ + close(connection->fd); + free(connection); +} + +void +wl_connection_copy(struct wl_connection *connection, void *data, size_t size) +{ + wl_buffer_copy(&connection->in, data, size); +} + +void +wl_connection_consume(struct wl_connection *connection, size_t size) +{ + connection->in.tail += size; +} + +static void +build_cmsg(struct wl_buffer *buffer, char *data, int *clen) +{ + struct cmsghdr *cmsg; + size_t size; + + size = buffer->head - buffer->tail; + if (size > 0) { + cmsg = (struct cmsghdr *) data; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(size); + wl_buffer_copy(buffer, CMSG_DATA(cmsg), size); + *clen = cmsg->cmsg_len; + } else { + *clen = 0; + } +} + +static void +close_fds(struct wl_buffer *buffer) +{ + int fds[32], i, count; + size_t size; + + size = buffer->head - buffer->tail; + if (size == 0) + return; + + wl_buffer_copy(buffer, fds, size); + count = size / sizeof fds[0]; + for (i = 0; i < count; i++) + close(fds[i]); + buffer->tail += size; +} + +static void +decode_cmsg(struct wl_buffer *buffer, struct msghdr *msg) +{ + struct cmsghdr *cmsg; + size_t size; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_RIGHTS) { + size = cmsg->cmsg_len - CMSG_LEN(0); + wl_buffer_put(buffer, CMSG_DATA(cmsg), size); + } + } +} + +int +wl_connection_data(struct wl_connection *connection, uint32_t mask) +{ + struct iovec iov[2]; + struct msghdr msg; + char cmsg[128]; + int len, count, clen; + + if (mask & WL_CONNECTION_WRITABLE) { + wl_buffer_get_iov(&connection->out, iov, &count); + + build_cmsg(&connection->fds_out, cmsg, &clen); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = count; + msg.msg_control = cmsg; + msg.msg_controllen = clen; + msg.msg_flags = 0; + + do { + len = sendmsg(connection->fd, &msg, MSG_NOSIGNAL); + } while (len < 0 && errno == EINTR); + + if (len == -1 && errno == EPIPE) { + return -1; + } else if (len < 0) { + fprintf(stderr, + "write error for connection %p, fd %d: %m\n", + connection, connection->fd); + return -1; + } + + close_fds(&connection->fds_out); + + connection->out.tail += len; + if (connection->out.tail == connection->out.head) + connection->update(connection, + WL_CONNECTION_READABLE, + connection->data); + } + + if (mask & WL_CONNECTION_READABLE) { + wl_buffer_put_iov(&connection->in, iov, &count); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = iov; + msg.msg_iovlen = count; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof cmsg; + msg.msg_flags = 0; + + do { + len = recvmsg(connection->fd, &msg, 0); + } while (len < 0 && errno == EINTR); + + if (len < 0) { + fprintf(stderr, + "read error from connection %p: %m (%d)\n", + connection, errno); + return -1; + } else if (len == 0) { + /* FIXME: Handle this better? */ + return -1; + } + + decode_cmsg(&connection->fds_in, &msg); + + connection->in.head += len; + } + + return connection->in.head - connection->in.tail; +} + +void +wl_connection_write(struct wl_connection *connection, + const void *data, size_t count) +{ + wl_buffer_put(&connection->out, data, count); + + if (connection->out.head - connection->out.tail == count) + connection->update(connection, + WL_CONNECTION_READABLE | + WL_CONNECTION_WRITABLE, + connection->data); +} + +static int +wl_message_size_extra(const struct wl_message *message) +{ + int i, extra; + + for (i = 0, extra = 0; message->signature[i]; i++) { + + switch (message->signature[i]) { + case 's': + case 'o': + extra += sizeof (void *); + break; + case 'a': + extra += sizeof (void *) + sizeof (struct wl_array); + break; + case 'h': + extra += sizeof (uint32_t); + break; + default: + break; + } + } + + return extra; +} + +struct wl_closure * +wl_connection_vmarshal(struct wl_connection *connection, + struct wl_object *sender, + uint32_t opcode, va_list ap, + const struct wl_message *message) +{ + struct wl_closure *closure = &connection->send_closure; + struct wl_object **objectp, *object; + uint32_t length, *p, *start, size; + int dup_fd; + struct wl_array **arrayp, *array; + const char **sp, *s; + char *extra; + int i, count, fd, extra_size, *fd_ptr; + + extra_size = wl_message_size_extra(message); + count = strlen(message->signature) + 2; + extra = (char *) closure->buffer; + start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)]; + p = &start[2]; + for (i = 2; i < count; i++) { + switch (message->signature[i - 2]) { + case 'u': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p; + *p++ = va_arg(ap, uint32_t); + break; + case 'i': + closure->types[i] = &ffi_type_sint32; + closure->args[i] = p; + *p++ = va_arg(ap, int32_t); + break; + case 's': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + sp = (const char **) extra; + extra += sizeof *sp; + + s = va_arg(ap, const char *); + length = s ? strlen(s) + 1: 0; + *p++ = length; + + if (length > 0) + *sp = (const char *) p; + else + *sp = NULL; + + memcpy(p, s, length); + p += DIV_ROUNDUP(length, sizeof *p); + break; + case 'o': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + objectp = (struct wl_object **) extra; + extra += sizeof *objectp; + + object = va_arg(ap, struct wl_object *); + *objectp = object; + *p++ = object ? object->id : 0; + break; + + case 'n': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p; + object = va_arg(ap, struct wl_object *); + *p++ = object->id; + break; + + case 'a': + closure->types[i] = &ffi_type_pointer; + closure->args[i] = extra; + arrayp = (struct wl_array **) extra; + extra += sizeof *arrayp; + + *arrayp = (struct wl_array *) extra; + extra += sizeof **arrayp; + + array = va_arg(ap, struct wl_array *); + if (array == NULL || array->size == 0) { + *p++ = 0; + break; + } + *p++ = array->size; + memcpy(p, array->data, array->size); + + (*arrayp)->size = array->size; + (*arrayp)->alloc = array->alloc; + (*arrayp)->data = p; + + p += DIV_ROUNDUP(array->size, sizeof *p); + break; + + case 'h': + closure->types[i] = &ffi_type_sint; + closure->args[i] = extra; + fd_ptr = (int *) extra; + extra += sizeof *fd_ptr; + + fd = va_arg(ap, int); + dup_fd = dup(fd); + if (dup_fd < 0) { + fprintf(stderr, "dup failed: %m"); + abort(); + } + *fd_ptr = dup_fd; + wl_buffer_put(&connection->fds_out, + &dup_fd, sizeof dup_fd); + break; + default: + assert(0); + break; + } + } + + size = (p - start) * sizeof *p; + start[0] = sender->id; + start[1] = opcode | (size << 16); + + closure->start = start; + closure->message = message; + closure->count = count; + + return closure; +} + +struct wl_closure * +wl_connection_demarshal(struct wl_connection *connection, + uint32_t size, + struct wl_hash_table *objects, + const struct wl_message *message) +{ + uint32_t *p, *next, *end, length; + int *fd; + char *extra, **s; + int i, count, extra_space; + struct wl_object **object; + struct wl_array **array; + struct wl_closure *closure = &connection->receive_closure; + + count = strlen(message->signature) + 2; + if (count > ARRAY_LENGTH(closure->types)) { + printf("too many args (%d)\n", count); + assert(0); + } + + extra_space = wl_message_size_extra(message); + if (sizeof closure->buffer < size + extra_space) { + printf("request too big, should malloc tmp buffer here\n"); + assert(0); + } + + closure->message = message; + closure->types[0] = &ffi_type_pointer; + closure->types[1] = &ffi_type_pointer; + + wl_connection_copy(connection, closure->buffer, size); + p = &closure->buffer[2]; + end = (uint32_t *) ((char *) (p + size)); + extra = (char *) end; + for (i = 2; i < count; i++) { + if (p + 1 > end) { + printf("message too short, " + "object (%d), message %s(%s)\n", + *p, message->name, message->signature); + errno = EINVAL; + goto err; + } + + switch (message->signature[i - 2]) { + case 'u': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p++; + break; + case 'i': + closure->types[i] = &ffi_type_sint32; + closure->args[i] = p++; + break; + case 's': + closure->types[i] = &ffi_type_pointer; + length = *p++; + + next = p + DIV_ROUNDUP(length, sizeof *p); + if (next > end) { + printf("message too short, " + "object (%d), message %s(%s)\n", + *p, message->name, message->signature); + errno = EINVAL; + goto err; + } + + s = (char **) extra; + extra += sizeof *s; + closure->args[i] = s; + + if (length == 0) { + *s = NULL; + } else { + *s = (char *) p; + } + + if (length > 0 && (*s)[length - 1] != '\0') { + printf("string not nul-terminated, " + "message %s(%s)\n", + message->name, message->signature); + errno = EINVAL; + goto err; + } + p = next; + break; + case 'o': + closure->types[i] = &ffi_type_pointer; + object = (struct wl_object **) extra; + extra += sizeof *object; + closure->args[i] = object; + + *object = wl_hash_table_lookup(objects, *p); + if (*object == NULL && *p != 0) { + printf("unknown object (%d), message %s(%s)\n", + *p, message->name, message->signature); + errno = EINVAL; + goto err; + } + + p++; + break; + case 'n': + closure->types[i] = &ffi_type_uint32; + closure->args[i] = p; + object = wl_hash_table_lookup(objects, *p); + if (object != NULL) { + printf("not a new object (%d), " + "message %s(%s)\n", + *p, message->name, message->signature); + errno = EINVAL; + goto err; + } + p++; + break; + case 'a': + closure->types[i] = &ffi_type_pointer; + length = *p++; + + next = p + DIV_ROUNDUP(length, sizeof *p); + if (next > end) { + printf("message too short, " + "object (%d), message %s(%s)\n", + *p, message->name, message->signature); + errno = EINVAL; + goto err; + } + + array = (struct wl_array **) extra; + extra += sizeof *array; + closure->args[i] = array; + + *array = (struct wl_array *) extra; + extra += sizeof **array; + + (*array)->size = length; + (*array)->alloc = 0; + (*array)->data = p; + p = next; + break; + case 'h': + closure->types[i] = &ffi_type_sint; + + fd = (int *) extra; + extra += sizeof *fd; + closure->args[i] = fd; + + wl_buffer_copy(&connection->fds_in, fd, sizeof *fd); + connection->fds_in.tail += sizeof *fd; + break; + default: + printf("unknown type\n"); + assert(0); + break; + } + } + + closure->count = i; + ffi_prep_cif(&closure->cif, FFI_DEFAULT_ABI, + closure->count, &ffi_type_uint32, closure->types); + + wl_connection_consume(connection, size); + + return closure; + + err: + closure->count = i; + wl_closure_destroy(closure); + wl_connection_consume(connection, size); + + return NULL; +} + +void +wl_closure_invoke(struct wl_closure *closure, + struct wl_object *target, void (*func)(void), void *data) +{ + int result; + + closure->args[0] = &data; + closure->args[1] = ⌖ + + ffi_call(&closure->cif, func, &result, closure->args); +} + +void +wl_closure_send(struct wl_closure *closure, struct wl_connection *connection) +{ + uint32_t size; + + size = closure->start[1] >> 16; + wl_connection_write(connection, closure->start, size); +} + +void +wl_closure_print(struct wl_closure *closure, struct wl_object *target) +{ + union wl_value *value; + int i; + + fprintf(stderr, "%s@%d.%s(", + target->interface->name, target->id, + closure->message->name); + + for (i = 2; i < closure->count; i++) { + if (i > 2) + fprintf(stderr, ", "); + + value = closure->args[i]; + switch (closure->message->signature[i - 2]) { + case 'u': + fprintf(stderr, "%u", value->uint32); + break; + case 'i': + fprintf(stderr, "%d", value->uint32); + break; + case 's': + fprintf(stderr, "\"%s\"", value->string); + break; + case 'o': + if (value->object) + fprintf(stderr, "%s@%u", + value->object->interface->name, + value->object->id); + else + fprintf(stderr, "nil"); + break; + case 'n': + fprintf(stderr, "new id %u", value->uint32); + break; + case 'a': + fprintf(stderr, "array"); + break; + case 'h': + fprintf(stderr, "fd %d", value->uint32); + break; + } + } + + fprintf(stderr, ")\n"); +} + +void +wl_closure_destroy(struct wl_closure *closure) +{ +} diff --git a/src/3rdparty/wayland/connection.h b/src/3rdparty/wayland/connection.h new file mode 100644 index 000000000..413977dff --- /dev/null +++ b/src/3rdparty/wayland/connection.h @@ -0,0 +1,68 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _CONNECTION_H_ +#define _CONNECTION_H_ + +#include <stdarg.h> +#include "wayland-util.h" + +struct wl_connection; +struct wl_closure; + +#define WL_CONNECTION_READABLE 0x01 +#define WL_CONNECTION_WRITABLE 0x02 + +typedef int (*wl_connection_update_func_t)(struct wl_connection *connection, + uint32_t mask, void *data); + +struct wl_connection *wl_connection_create(int fd, + wl_connection_update_func_t update, + void *data); +void wl_connection_destroy(struct wl_connection *connection); +void wl_connection_copy(struct wl_connection *connection, void *data, size_t size); +void wl_connection_consume(struct wl_connection *connection, size_t size); +int wl_connection_data(struct wl_connection *connection, uint32_t mask); +void wl_connection_write(struct wl_connection *connection, const void *data, size_t count); + +struct wl_closure * +wl_connection_vmarshal(struct wl_connection *connection, + struct wl_object *sender, + uint32_t opcode, va_list ap, + const struct wl_message *message); + +struct wl_closure * +wl_connection_demarshal(struct wl_connection *connection, + uint32_t size, + struct wl_hash_table *objects, + const struct wl_message *message); +void +wl_closure_invoke(struct wl_closure *closure, + struct wl_object *target, void (*func)(void), void *data); +void +wl_closure_send(struct wl_closure *closure, struct wl_connection *connection); +void +wl_closure_print(struct wl_closure *closure, struct wl_object *target); +void +wl_closure_destroy(struct wl_closure *closure); + +#endif diff --git a/src/3rdparty/wayland/event-loop.c b/src/3rdparty/wayland/event-loop.c new file mode 100644 index 000000000..bf2a9aafb --- /dev/null +++ b/src/3rdparty/wayland/event-loop.c @@ -0,0 +1,444 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stddef.h> +#include <stdio.h> +#include <errno.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/epoll.h> +#include <sys/signalfd.h> +#include <sys/timerfd.h> +#include <unistd.h> +#include <assert.h> +#include "wayland-server.h" + +struct wl_event_loop { + int epoll_fd; + struct wl_list idle_list; +}; + +struct wl_event_source_interface { + void (*dispatch)(struct wl_event_source *source, + struct epoll_event *ep); + int (*remove)(struct wl_event_source *source); +}; + +struct wl_event_source { + struct wl_event_source_interface *interface; + struct wl_event_loop *loop; +}; + +struct wl_event_source_fd { + struct wl_event_source base; + int fd; + wl_event_loop_fd_func_t func; + void *data; +}; + +static void +wl_event_source_fd_dispatch(struct wl_event_source *source, + struct epoll_event *ep) +{ + struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source; + uint32_t mask; + + mask = 0; + if (ep->events & EPOLLIN) + mask |= WL_EVENT_READABLE; + if (ep->events & EPOLLOUT) + mask |= WL_EVENT_WRITEABLE; + + fd_source->func(fd_source->fd, mask, fd_source->data); +} + +static int +wl_event_source_fd_remove(struct wl_event_source *source) +{ + struct wl_event_source_fd *fd_source = + (struct wl_event_source_fd *) source; + struct wl_event_loop *loop = source->loop; + int fd; + + fd = fd_source->fd; + free(source); + + return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); +} + +struct wl_event_source_interface fd_source_interface = { + wl_event_source_fd_dispatch, + wl_event_source_fd_remove +}; + +WL_EXPORT struct wl_event_source * +wl_event_loop_add_fd(struct wl_event_loop *loop, + int fd, uint32_t mask, + wl_event_loop_fd_func_t func, + void *data) +{ + struct wl_event_source_fd *source; + struct epoll_event ep; + + source = malloc(sizeof *source); + if (source == NULL) + return NULL; + + source->base.interface = &fd_source_interface; + source->base.loop = loop; + source->fd = fd; + source->func = func; + source->data = data; + + memset(&ep, 0, sizeof ep); + if (mask & WL_EVENT_READABLE) + ep.events |= EPOLLIN; + if (mask & WL_EVENT_WRITEABLE) + ep.events |= EPOLLOUT; + ep.data.ptr = source; + + if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { + free(source); + return NULL; + } + + return &source->base; +} + +WL_EXPORT int +wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask) +{ + struct wl_event_source_fd *fd_source = + (struct wl_event_source_fd *) source; + struct wl_event_loop *loop = source->loop; + struct epoll_event ep; + + memset(&ep, 0, sizeof ep); + if (mask & WL_EVENT_READABLE) + ep.events |= EPOLLIN; + if (mask & WL_EVENT_WRITEABLE) + ep.events |= EPOLLOUT; + ep.data.ptr = source; + + return epoll_ctl(loop->epoll_fd, + EPOLL_CTL_MOD, fd_source->fd, &ep); +} + +struct wl_event_source_timer { + struct wl_event_source base; + int fd; + wl_event_loop_timer_func_t func; + void *data; +}; + +static void +wl_event_source_timer_dispatch(struct wl_event_source *source, + struct epoll_event *ep) +{ + struct wl_event_source_timer *timer_source = + (struct wl_event_source_timer *) source; + uint64_t expires; + + read(timer_source->fd, &expires, sizeof expires); + + timer_source->func(timer_source->data); +} + +static int +wl_event_source_timer_remove(struct wl_event_source *source) +{ + struct wl_event_source_timer *timer_source = + (struct wl_event_source_timer *) source; + struct wl_event_loop *loop = source->loop; + int fd; + + fd = timer_source->fd; + free(source); + + return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); +} + +struct wl_event_source_interface timer_source_interface = { + wl_event_source_timer_dispatch, + wl_event_source_timer_remove +}; + +WL_EXPORT struct wl_event_source * +wl_event_loop_add_timer(struct wl_event_loop *loop, + wl_event_loop_timer_func_t func, + void *data) +{ + struct wl_event_source_timer *source; + struct epoll_event ep; + + source = malloc(sizeof *source); + if (source == NULL) + return NULL; + + source->base.interface = &timer_source_interface; + source->base.loop = loop; + + source->fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (source->fd < 0) { + fprintf(stderr, "could not create timerfd\n: %m"); + free(source); + return NULL; + } + + source->func = func; + source->data = data; + + memset(&ep, 0, sizeof ep); + ep.events = EPOLLIN; + ep.data.ptr = source; + + if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) { + free(source); + return NULL; + } + + return &source->base; +} + +WL_EXPORT int +wl_event_source_timer_update(struct wl_event_source *source, int ms_delay) +{ + struct wl_event_source_timer *timer_source = + (struct wl_event_source_timer *) source; + struct itimerspec its; + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = ms_delay * 1000 * 1000; + if (timerfd_settime(timer_source->fd, 0, &its, NULL) < 0) { + fprintf(stderr, "could not set timerfd\n: %m"); + return -1; + } + + return 0; +} + +struct wl_event_source_signal { + struct wl_event_source base; + int fd; + int signal_number; + wl_event_loop_signal_func_t func; + void *data; +}; + +static void +wl_event_source_signal_dispatch(struct wl_event_source *source, + struct epoll_event *ep) +{ + struct wl_event_source_signal *signal_source = + (struct wl_event_source_signal *) source; + struct signalfd_siginfo signal_info; + + read(signal_source->fd, &signal_info, sizeof signal_info); + + signal_source->func(signal_source->signal_number, signal_source->data); +} + +static int +wl_event_source_signal_remove(struct wl_event_source *source) +{ + struct wl_event_source_signal *signal_source = + (struct wl_event_source_signal *) source; + struct wl_event_loop *loop = source->loop; + int fd; + + fd = signal_source->fd; + free(source); + + return epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, fd, NULL); +} + +struct wl_event_source_interface signal_source_interface = { + wl_event_source_signal_dispatch, + wl_event_source_signal_remove +}; + +WL_EXPORT struct wl_event_source * +wl_event_loop_add_signal(struct wl_event_loop *loop, + int signal_number, + wl_event_loop_signal_func_t func, + void *data) +{ + struct wl_event_source_signal *source; + struct epoll_event ep; + sigset_t mask; + + source = malloc(sizeof *source); + if (source == NULL) + return NULL; + + source->base.interface = &signal_source_interface; + source->base.loop = loop; + + sigemptyset(&mask); + sigaddset(&mask, signal_number); + source->fd = signalfd(-1, &mask, 0); + if (source->fd < 0) { + fprintf(stderr, "could not create fd to watch signal\n: %m"); + free(source); + return NULL; + } + sigprocmask(SIG_BLOCK, &mask, NULL); + + source->func = func; + source->data = data; + + memset(&ep, 0, sizeof ep); + ep.events = EPOLLIN; + ep.data.ptr = source; + + if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) { + free(source); + return NULL; + } + + return &source->base; +} + +struct wl_event_source_idle { + struct wl_event_source base; + struct wl_list link; + wl_event_loop_idle_func_t func; + void *data; +}; + +static void +wl_event_source_idle_dispatch(struct wl_event_source *source, + struct epoll_event *ep) +{ + assert(0); +} + +static int +wl_event_source_idle_remove(struct wl_event_source *source) +{ + struct wl_event_source_idle *idle_source = + (struct wl_event_source_idle *) source; + + wl_list_remove(&idle_source->link); + free(source); + + return 0; +} + +struct wl_event_source_interface idle_source_interface = { + wl_event_source_idle_dispatch, + wl_event_source_idle_remove +}; + +WL_EXPORT struct wl_event_source * +wl_event_loop_add_idle(struct wl_event_loop *loop, + wl_event_loop_idle_func_t func, + void *data) +{ + struct wl_event_source_idle *source; + + source = malloc(sizeof *source); + if (source == NULL) + return NULL; + + source->base.interface = &idle_source_interface; + source->base.loop = loop; + + source->func = func; + source->data = data; + wl_list_insert(loop->idle_list.prev, &source->link); + + return &source->base; +} + +WL_EXPORT int +wl_event_source_remove(struct wl_event_source *source) +{ + source->interface->remove(source); + + return 0; +} + +WL_EXPORT struct wl_event_loop * +wl_event_loop_create(void) +{ + struct wl_event_loop *loop; + + loop = malloc(sizeof *loop); + if (loop == NULL) + return NULL; + + loop->epoll_fd = epoll_create(16); + if (loop->epoll_fd < 0) { + free(loop); + return NULL; + } + wl_list_init(&loop->idle_list); + + return loop; +} + +WL_EXPORT void +wl_event_loop_destroy(struct wl_event_loop *loop) +{ + close(loop->epoll_fd); + free(loop); +} + +WL_EXPORT int +wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout) +{ + struct epoll_event ep[32]; + struct wl_event_source *source; + struct wl_event_source_idle *idle; + int i, count; + + count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); + if (count < 0) + return -1; + + for (i = 0; i < count; i++) { + source = ep[i].data.ptr; + source->interface->dispatch(source, &ep[i]); + } + + while (!wl_list_empty(&loop->idle_list)) { + idle = container_of(loop->idle_list.next, + struct wl_event_source_idle, link); + wl_list_remove(&idle->link); + idle->func(idle->data); + free(idle); + } + + return 0; +} + +WL_EXPORT int +wl_event_loop_get_fd(struct wl_event_loop *loop) +{ + return loop->epoll_fd; +} diff --git a/src/3rdparty/wayland/server/server.pro b/src/3rdparty/wayland/server/server.pro new file mode 100644 index 000000000..2c1788ce2 --- /dev/null +++ b/src/3rdparty/wayland/server/server.pro @@ -0,0 +1,20 @@ +TEMPLATE = lib +TARGET = wayland-server +DESTDIR=$$PWD/../../../../lib/ + +CONFIG -= qt +CONFIG += shared + +INCLUDEPATH += $$PWD/.. \ + $$PWD/../../ffi + +LIBS += -L $$PWD/../../../../lib/ -lffi + +SOURCES = ../event-loop.c \ + ../wayland-server.c \ + ../wayland-protocol.c \ + ../connection.c \ + ../wayland-util.c \ + ../wayland-hash.c + +OBJECTS_DIR = .obj diff --git a/src/3rdparty/wayland/wayland-client-protocol.h b/src/3rdparty/wayland/wayland-client-protocol.h new file mode 100644 index 000000000..0af6645bb --- /dev/null +++ b/src/3rdparty/wayland/wayland-client-protocol.h @@ -0,0 +1,919 @@ +/* + * Copyright © 2010 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + +#ifndef WAYLAND_CLIENT_PROTOCOL_H +#define WAYLAND_CLIENT_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; + +struct wl_display; +struct wl_compositor; +struct wl_drm; +struct wl_shm; +struct wl_buffer; +struct wl_shell; +struct wl_selection; +struct wl_selection_offer; +struct wl_drag; +struct wl_drag_offer; +struct wl_surface; +struct wl_input_device; +struct wl_output; +struct wl_visual; + +struct wl_proxy; + +extern void +wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...); +extern struct wl_proxy * +wl_proxy_create(struct wl_proxy *factory, + const struct wl_interface *interface); +extern struct wl_proxy * +wl_proxy_create_for_id(struct wl_display *display, + const struct wl_interface *interface, uint32_t id); +extern void +wl_proxy_destroy(struct wl_proxy *proxy); + +extern int +wl_proxy_add_listener(struct wl_proxy *proxy, + void (**implementation)(void), void *data); + +extern void +wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data); + +extern void * +wl_proxy_get_user_data(struct wl_proxy *proxy); + +extern const struct wl_interface wl_display_interface; +extern const struct wl_interface wl_compositor_interface; +extern const struct wl_interface wl_drm_interface; +extern const struct wl_interface wl_shm_interface; +extern const struct wl_interface wl_buffer_interface; +extern const struct wl_interface wl_shell_interface; +extern const struct wl_interface wl_selection_interface; +extern const struct wl_interface wl_selection_offer_interface; +extern const struct wl_interface wl_drag_interface; +extern const struct wl_interface wl_drag_offer_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wl_input_device_interface; +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_visual_interface; + +struct wl_display_listener { + void (*invalid_object)(void *data, + struct wl_display *display, + uint32_t object_id); + void (*invalid_method)(void *data, + struct wl_display *display, + uint32_t object_id, + uint32_t opcode); + void (*no_memory)(void *data, + struct wl_display *display); + void (*global)(void *data, + struct wl_display *display, + uint32_t id, + const char *name, + uint32_t version); + void (*range)(void *data, + struct wl_display *display, + uint32_t base); + void (*key)(void *data, + struct wl_display *display, + uint32_t key, + uint32_t time); +}; + +static inline int +wl_display_add_listener(struct wl_display *display, + const struct wl_display_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) display, + (void (**)(void)) listener, data); +} + +#define WL_DISPLAY_SYNC 0 +#define WL_DISPLAY_FRAME 1 + +static inline void +wl_display_set_user_data(struct wl_display *display, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) display, user_data); +} + +static inline void * +wl_display_get_user_data(struct wl_display *display) +{ + return wl_proxy_get_user_data((struct wl_proxy *) display); +} + +static inline void +wl_display_sync(struct wl_display *display, uint32_t key) +{ + wl_proxy_marshal((struct wl_proxy *) display, + WL_DISPLAY_SYNC, key); +} + +static inline void +wl_display_frame(struct wl_display *display, uint32_t key) +{ + wl_proxy_marshal((struct wl_proxy *) display, + WL_DISPLAY_FRAME, key); +} + +#define WL_COMPOSITOR_CREATE_SURFACE 0 + +static inline struct wl_compositor * +wl_compositor_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_compositor *) + wl_proxy_create_for_id(display, &wl_compositor_interface, id); +} + +static inline void +wl_compositor_set_user_data(struct wl_compositor *compositor, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) compositor, user_data); +} + +static inline void * +wl_compositor_get_user_data(struct wl_compositor *compositor) +{ + return wl_proxy_get_user_data((struct wl_proxy *) compositor); +} + +static inline void +wl_compositor_destroy(struct wl_compositor *compositor) +{ + wl_proxy_destroy((struct wl_proxy *) compositor); +} + +static inline struct wl_surface * +wl_compositor_create_surface(struct wl_compositor *compositor) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) compositor, + &wl_surface_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) compositor, + WL_COMPOSITOR_CREATE_SURFACE, id); + + return (struct wl_surface *) id; +} + +struct wl_drm_listener { + void (*device)(void *data, + struct wl_drm *drm, + const char *name); + void (*authenticated)(void *data, + struct wl_drm *drm); +}; + +static inline int +wl_drm_add_listener(struct wl_drm *drm, + const struct wl_drm_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) drm, + (void (**)(void)) listener, data); +} + +#define WL_DRM_AUTHENTICATE 0 +#define WL_DRM_CREATE_BUFFER 1 + +static inline struct wl_drm * +wl_drm_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_drm *) + wl_proxy_create_for_id(display, &wl_drm_interface, id); +} + +static inline void +wl_drm_set_user_data(struct wl_drm *drm, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) drm, user_data); +} + +static inline void * +wl_drm_get_user_data(struct wl_drm *drm) +{ + return wl_proxy_get_user_data((struct wl_proxy *) drm); +} + +static inline void +wl_drm_destroy(struct wl_drm *drm) +{ + wl_proxy_destroy((struct wl_proxy *) drm); +} + +static inline void +wl_drm_authenticate(struct wl_drm *drm, uint32_t id) +{ + wl_proxy_marshal((struct wl_proxy *) drm, + WL_DRM_AUTHENTICATE, id); +} + +static inline struct wl_buffer * +wl_drm_create_buffer(struct wl_drm *drm, uint32_t name, int width, int height, uint32_t stride, struct wl_visual *visual) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) drm, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) drm, + WL_DRM_CREATE_BUFFER, id, name, width, height, stride, visual); + + return (struct wl_buffer *) id; +} + +#define WL_SHM_CREATE_BUFFER 0 + +static inline struct wl_shm * +wl_shm_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_shm *) + wl_proxy_create_for_id(display, &wl_shm_interface, id); +} + +static inline void +wl_shm_set_user_data(struct wl_shm *shm, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) shm, user_data); +} + +static inline void * +wl_shm_get_user_data(struct wl_shm *shm) +{ + return wl_proxy_get_user_data((struct wl_proxy *) shm); +} + +static inline void +wl_shm_destroy(struct wl_shm *shm) +{ + wl_proxy_destroy((struct wl_proxy *) shm); +} + +static inline struct wl_buffer * +wl_shm_create_buffer(struct wl_shm *shm, int fd, int width, int height, uint32_t stride, struct wl_visual *visual) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) shm, + &wl_buffer_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) shm, + WL_SHM_CREATE_BUFFER, id, fd, width, height, stride, visual); + + return (struct wl_buffer *) id; +} + +#define WL_BUFFER_DESTROY 0 + +static inline struct wl_buffer * +wl_buffer_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_buffer *) + wl_proxy_create_for_id(display, &wl_buffer_interface, id); +} + +static inline void +wl_buffer_set_user_data(struct wl_buffer *buffer, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) buffer, user_data); +} + +static inline void * +wl_buffer_get_user_data(struct wl_buffer *buffer) +{ + return wl_proxy_get_user_data((struct wl_proxy *) buffer); +} + +static inline void +wl_buffer_destroy(struct wl_buffer *buffer) +{ + wl_proxy_marshal((struct wl_proxy *) buffer, + WL_BUFFER_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) buffer); +} + +#ifndef WL_SHELL_RESIZE_ENUM +#define WL_SHELL_RESIZE_ENUM +enum wl_shell_resize { + WL_SHELL_RESIZE_NONE = 0, + WL_SHELL_RESIZE_TOP = 1, + WL_SHELL_RESIZE_BOTTOM = 2, + WL_SHELL_RESIZE_LEFT = 4, + WL_SHELL_RESIZE_TOP_LEFT = 5, + WL_SHELL_RESIZE_BOTTOM_LEFT = 6, + WL_SHELL_RESIZE_RIGHT = 8, + WL_SHELL_RESIZE_TOP_RIGHT = 9, + WL_SHELL_RESIZE_BOTTOM_RIGHT = 10, +}; +#endif /* WL_SHELL_RESIZE_ENUM */ + +struct wl_shell_listener { + void (*configure)(void *data, + struct wl_shell *shell, + uint32_t time, + uint32_t edges, + struct wl_surface *surface, + int width, + int height); +}; + +static inline int +wl_shell_add_listener(struct wl_shell *shell, + const struct wl_shell_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) shell, + (void (**)(void)) listener, data); +} + +#define WL_SHELL_MOVE 0 +#define WL_SHELL_RESIZE 1 +#define WL_SHELL_CREATE_DRAG 2 +#define WL_SHELL_CREATE_SELECTION 3 + +static inline struct wl_shell * +wl_shell_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_shell *) + wl_proxy_create_for_id(display, &wl_shell_interface, id); +} + +static inline void +wl_shell_set_user_data(struct wl_shell *shell, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) shell, user_data); +} + +static inline void * +wl_shell_get_user_data(struct wl_shell *shell) +{ + return wl_proxy_get_user_data((struct wl_proxy *) shell); +} + +static inline void +wl_shell_destroy(struct wl_shell *shell) +{ + wl_proxy_destroy((struct wl_proxy *) shell); +} + +static inline void +wl_shell_move(struct wl_shell *shell, struct wl_surface *surface, struct wl_input_device *input_device, uint32_t time) +{ + wl_proxy_marshal((struct wl_proxy *) shell, + WL_SHELL_MOVE, surface, input_device, time); +} + +static inline void +wl_shell_resize(struct wl_shell *shell, struct wl_surface *surface, struct wl_input_device *input_device, uint32_t time, uint32_t edges) +{ + wl_proxy_marshal((struct wl_proxy *) shell, + WL_SHELL_RESIZE, surface, input_device, time, edges); +} + +static inline struct wl_drag * +wl_shell_create_drag(struct wl_shell *shell) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) shell, + &wl_drag_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) shell, + WL_SHELL_CREATE_DRAG, id); + + return (struct wl_drag *) id; +} + +static inline struct wl_selection * +wl_shell_create_selection(struct wl_shell *shell) +{ + struct wl_proxy *id; + + id = wl_proxy_create((struct wl_proxy *) shell, + &wl_selection_interface); + if (!id) + return NULL; + + wl_proxy_marshal((struct wl_proxy *) shell, + WL_SHELL_CREATE_SELECTION, id); + + return (struct wl_selection *) id; +} + +struct wl_selection_listener { + void (*send)(void *data, + struct wl_selection *selection, + const char *mime_type, + int fd); + void (*cancelled)(void *data, + struct wl_selection *selection); +}; + +static inline int +wl_selection_add_listener(struct wl_selection *selection, + const struct wl_selection_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) selection, + (void (**)(void)) listener, data); +} + +#define WL_SELECTION_OFFER 0 +#define WL_SELECTION_ACTIVATE 1 +#define WL_SELECTION_DESTROY 2 + +static inline struct wl_selection * +wl_selection_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_selection *) + wl_proxy_create_for_id(display, &wl_selection_interface, id); +} + +static inline void +wl_selection_set_user_data(struct wl_selection *selection, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) selection, user_data); +} + +static inline void * +wl_selection_get_user_data(struct wl_selection *selection) +{ + return wl_proxy_get_user_data((struct wl_proxy *) selection); +} + +static inline void +wl_selection_offer(struct wl_selection *selection, const char *type) +{ + wl_proxy_marshal((struct wl_proxy *) selection, + WL_SELECTION_OFFER, type); +} + +static inline void +wl_selection_activate(struct wl_selection *selection, struct wl_input_device *input_device, uint32_t time) +{ + wl_proxy_marshal((struct wl_proxy *) selection, + WL_SELECTION_ACTIVATE, input_device, time); +} + +static inline void +wl_selection_destroy(struct wl_selection *selection) +{ + wl_proxy_marshal((struct wl_proxy *) selection, + WL_SELECTION_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) selection); +} + +struct wl_selection_offer_listener { + void (*offer)(void *data, + struct wl_selection_offer *selection_offer, + const char *type); + void (*keyboard_focus)(void *data, + struct wl_selection_offer *selection_offer, + struct wl_input_device *input_device); +}; + +static inline int +wl_selection_offer_add_listener(struct wl_selection_offer *selection_offer, + const struct wl_selection_offer_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) selection_offer, + (void (**)(void)) listener, data); +} + +#define WL_SELECTION_OFFER_RECEIVE 0 + +static inline struct wl_selection_offer * +wl_selection_offer_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_selection_offer *) + wl_proxy_create_for_id(display, &wl_selection_offer_interface, id); +} + +static inline void +wl_selection_offer_set_user_data(struct wl_selection_offer *selection_offer, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) selection_offer, user_data); +} + +static inline void * +wl_selection_offer_get_user_data(struct wl_selection_offer *selection_offer) +{ + return wl_proxy_get_user_data((struct wl_proxy *) selection_offer); +} + +static inline void +wl_selection_offer_destroy(struct wl_selection_offer *selection_offer) +{ + wl_proxy_destroy((struct wl_proxy *) selection_offer); +} + +static inline void +wl_selection_offer_receive(struct wl_selection_offer *selection_offer, const char *mime_type, int fd) +{ + wl_proxy_marshal((struct wl_proxy *) selection_offer, + WL_SELECTION_OFFER_RECEIVE, mime_type, fd); +} + +struct wl_drag_listener { + void (*target)(void *data, + struct wl_drag *drag, + const char *mime_type); + void (*finish)(void *data, + struct wl_drag *drag, + int fd); + void (*reject)(void *data, + struct wl_drag *drag); +}; + +static inline int +wl_drag_add_listener(struct wl_drag *drag, + const struct wl_drag_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) drag, + (void (**)(void)) listener, data); +} + +#define WL_DRAG_OFFER 0 +#define WL_DRAG_ACTIVATE 1 +#define WL_DRAG_DESTROY 2 + +static inline struct wl_drag * +wl_drag_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_drag *) + wl_proxy_create_for_id(display, &wl_drag_interface, id); +} + +static inline void +wl_drag_set_user_data(struct wl_drag *drag, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) drag, user_data); +} + +static inline void * +wl_drag_get_user_data(struct wl_drag *drag) +{ + return wl_proxy_get_user_data((struct wl_proxy *) drag); +} + +static inline void +wl_drag_offer(struct wl_drag *drag, const char *type) +{ + wl_proxy_marshal((struct wl_proxy *) drag, + WL_DRAG_OFFER, type); +} + +static inline void +wl_drag_activate(struct wl_drag *drag, struct wl_surface *surface, struct wl_input_device *input_device, uint32_t time) +{ + wl_proxy_marshal((struct wl_proxy *) drag, + WL_DRAG_ACTIVATE, surface, input_device, time); +} + +static inline void +wl_drag_destroy(struct wl_drag *drag) +{ + wl_proxy_marshal((struct wl_proxy *) drag, + WL_DRAG_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) drag); +} + +struct wl_drag_offer_listener { + void (*offer)(void *data, + struct wl_drag_offer *drag_offer, + const char *type); + void (*pointer_focus)(void *data, + struct wl_drag_offer *drag_offer, + uint32_t time, + struct wl_surface *surface, + int x, + int y, + int surface_x, + int surface_y); + void (*motion)(void *data, + struct wl_drag_offer *drag_offer, + uint32_t time, + int x, + int y, + int surface_x, + int surface_y); + void (*drop)(void *data, + struct wl_drag_offer *drag_offer); +}; + +static inline int +wl_drag_offer_add_listener(struct wl_drag_offer *drag_offer, + const struct wl_drag_offer_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) drag_offer, + (void (**)(void)) listener, data); +} + +#define WL_DRAG_OFFER_ACCEPT 0 +#define WL_DRAG_OFFER_RECEIVE 1 +#define WL_DRAG_OFFER_REJECT 2 + +static inline struct wl_drag_offer * +wl_drag_offer_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_drag_offer *) + wl_proxy_create_for_id(display, &wl_drag_offer_interface, id); +} + +static inline void +wl_drag_offer_set_user_data(struct wl_drag_offer *drag_offer, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) drag_offer, user_data); +} + +static inline void * +wl_drag_offer_get_user_data(struct wl_drag_offer *drag_offer) +{ + return wl_proxy_get_user_data((struct wl_proxy *) drag_offer); +} + +static inline void +wl_drag_offer_destroy(struct wl_drag_offer *drag_offer) +{ + wl_proxy_destroy((struct wl_proxy *) drag_offer); +} + +static inline void +wl_drag_offer_accept(struct wl_drag_offer *drag_offer, uint32_t time, const char *type) +{ + wl_proxy_marshal((struct wl_proxy *) drag_offer, + WL_DRAG_OFFER_ACCEPT, time, type); +} + +static inline void +wl_drag_offer_receive(struct wl_drag_offer *drag_offer, int fd) +{ + wl_proxy_marshal((struct wl_proxy *) drag_offer, + WL_DRAG_OFFER_RECEIVE, fd); +} + +static inline void +wl_drag_offer_reject(struct wl_drag_offer *drag_offer) +{ + wl_proxy_marshal((struct wl_proxy *) drag_offer, + WL_DRAG_OFFER_REJECT); +} + +#define WL_SURFACE_DESTROY 0 +#define WL_SURFACE_ATTACH 1 +#define WL_SURFACE_MAP_TOPLEVEL 2 +#define WL_SURFACE_MAP_TRANSIENT 3 +#define WL_SURFACE_MAP_FULLSCREEN 4 +#define WL_SURFACE_DAMAGE 5 + +static inline struct wl_surface * +wl_surface_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_surface *) + wl_proxy_create_for_id(display, &wl_surface_interface, id); +} + +static inline void +wl_surface_set_user_data(struct wl_surface *surface, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) surface, user_data); +} + +static inline void * +wl_surface_get_user_data(struct wl_surface *surface) +{ + return wl_proxy_get_user_data((struct wl_proxy *) surface); +} + +static inline void +wl_surface_destroy(struct wl_surface *surface) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_DESTROY); + + wl_proxy_destroy((struct wl_proxy *) surface); +} + +static inline void +wl_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer, int x, int y) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_ATTACH, buffer, x, y); +} + +static inline void +wl_surface_map_toplevel(struct wl_surface *surface) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_MAP_TOPLEVEL); +} + +static inline void +wl_surface_map_transient(struct wl_surface *surface, struct wl_surface *parent, int x, int y, uint32_t flags) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_MAP_TRANSIENT, parent, x, y, flags); +} + +static inline void +wl_surface_map_fullscreen(struct wl_surface *surface) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_MAP_FULLSCREEN); +} + +static inline void +wl_surface_damage(struct wl_surface *surface, int x, int y, int width, int height) +{ + wl_proxy_marshal((struct wl_proxy *) surface, + WL_SURFACE_DAMAGE, x, y, width, height); +} + +struct wl_input_device_listener { + void (*motion)(void *data, + struct wl_input_device *input_device, + uint32_t time, + int x, + int y, + int surface_x, + int surface_y); + void (*button)(void *data, + struct wl_input_device *input_device, + uint32_t time, + uint32_t button, + uint32_t state); + void (*key)(void *data, + struct wl_input_device *input_device, + uint32_t time, + uint32_t key, + uint32_t state); + void (*pointer_focus)(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + int x, + int y, + int surface_x, + int surface_y); + void (*keyboard_focus)(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +static inline int +wl_input_device_add_listener(struct wl_input_device *input_device, + const struct wl_input_device_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) input_device, + (void (**)(void)) listener, data); +} + +#define WL_INPUT_DEVICE_ATTACH 0 + +static inline struct wl_input_device * +wl_input_device_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_input_device *) + wl_proxy_create_for_id(display, &wl_input_device_interface, id); +} + +static inline void +wl_input_device_set_user_data(struct wl_input_device *input_device, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) input_device, user_data); +} + +static inline void * +wl_input_device_get_user_data(struct wl_input_device *input_device) +{ + return wl_proxy_get_user_data((struct wl_proxy *) input_device); +} + +static inline void +wl_input_device_destroy(struct wl_input_device *input_device) +{ + wl_proxy_destroy((struct wl_proxy *) input_device); +} + +static inline void +wl_input_device_attach(struct wl_input_device *input_device, uint32_t time, struct wl_buffer *buffer, int hotspot_x, int hotspot_y) +{ + wl_proxy_marshal((struct wl_proxy *) input_device, + WL_INPUT_DEVICE_ATTACH, time, buffer, hotspot_x, hotspot_y); +} + +struct wl_output_listener { + void (*geometry)(void *data, + struct wl_output *output, + int x, + int y, + int width, + int height); +}; + +static inline int +wl_output_add_listener(struct wl_output *output, + const struct wl_output_listener *listener, void *data) +{ + return wl_proxy_add_listener((struct wl_proxy *) output, + (void (**)(void)) listener, data); +} + +static inline struct wl_output * +wl_output_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_output *) + wl_proxy_create_for_id(display, &wl_output_interface, id); +} + +static inline void +wl_output_set_user_data(struct wl_output *output, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) output, user_data); +} + +static inline void * +wl_output_get_user_data(struct wl_output *output) +{ + return wl_proxy_get_user_data((struct wl_proxy *) output); +} + +static inline void +wl_output_destroy(struct wl_output *output) +{ + wl_proxy_destroy((struct wl_proxy *) output); +} + +static inline struct wl_visual * +wl_visual_create(struct wl_display *display, uint32_t id) +{ + return (struct wl_visual *) + wl_proxy_create_for_id(display, &wl_visual_interface, id); +} + +static inline void +wl_visual_set_user_data(struct wl_visual *visual, void *user_data) +{ + wl_proxy_set_user_data((struct wl_proxy *) visual, user_data); +} + +static inline void * +wl_visual_get_user_data(struct wl_visual *visual) +{ + return wl_proxy_get_user_data((struct wl_proxy *) visual); +} + +static inline void +wl_visual_destroy(struct wl_visual *visual) +{ + wl_proxy_destroy((struct wl_proxy *) visual); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland-client.c b/src/3rdparty/wayland/wayland-client.c new file mode 100644 index 000000000..e3198c729 --- /dev/null +++ b/src/3rdparty/wayland/wayland-client.c @@ -0,0 +1,565 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <ctype.h> +#include <assert.h> +#include <sys/poll.h> + +#include "wayland-client-protocol.h" +#include "connection.h" +#include "wayland-util.h" +#include "wayland-client.h" + +struct wl_global_listener { + wl_display_global_func_t handler; + void *data; + struct wl_list link; +}; + +struct wl_listener { + void (**implementation)(void); + void *data; + struct wl_list link; +}; + +struct wl_proxy { + struct wl_object object; + struct wl_display *display; + struct wl_list listener_list; + void *user_data; +}; + +struct wl_sync_handler { + wl_display_sync_func_t func; + uint32_t key; + void *data; + struct wl_list link; +}; + +struct wl_frame_handler { + wl_display_frame_func_t func; + uint32_t key; + void *data; + struct wl_list link; +}; + +struct wl_display { + struct wl_proxy proxy; + struct wl_connection *connection; + int fd; + uint32_t id, id_count, next_range; + uint32_t mask; + struct wl_hash_table *objects; + struct wl_listener listener; + struct wl_list global_listener_list; + + struct wl_visual *argb_visual; + struct wl_visual *premultiplied_argb_visual; + struct wl_visual *rgb_visual; + + wl_display_update_func_t update; + void *update_data; + + wl_display_global_func_t global_handler; + void *global_handler_data; + + struct wl_list sync_list, frame_list; + uint32_t key; +}; + +static int wl_debug = 0; + +static int +connection_update(struct wl_connection *connection, + uint32_t mask, void *data) +{ + struct wl_display *display = data; + + display->mask = mask; + if (display->update) + return display->update(display->mask, + display->update_data); + + return 0; +} + +WL_EXPORT struct wl_global_listener * +wl_display_add_global_listener(struct wl_display *display, + wl_display_global_func_t handler, void *data) +{ + struct wl_global_listener *listener; + + listener = malloc(sizeof *listener); + if (listener == NULL) + return NULL; + + listener->handler = handler; + listener->data = data; + wl_list_insert(display->global_listener_list.prev, &listener->link); + + return listener; +} + +WL_EXPORT void +wl_display_remove_global_listener(struct wl_display *display, + struct wl_global_listener *listener) +{ + wl_list_remove(&listener->link); + free(listener); +} + +WL_EXPORT struct wl_proxy * +wl_proxy_create_for_id(struct wl_display *display, + const struct wl_interface *interface, uint32_t id) +{ + struct wl_proxy *proxy; + + proxy = malloc(sizeof *proxy); + if (proxy == NULL) + return NULL; + + proxy->object.interface = interface; + proxy->object.id = id; + proxy->display = display; + wl_list_init(&proxy->listener_list); + wl_hash_table_insert(display->objects, proxy->object.id, proxy); + + return proxy; +} + +WL_EXPORT struct wl_proxy * +wl_proxy_create(struct wl_proxy *factory, + const struct wl_interface *interface) +{ + return wl_proxy_create_for_id(factory->display, interface, + wl_display_allocate_id(factory->display)); +} + +WL_EXPORT void +wl_proxy_destroy(struct wl_proxy *proxy) +{ + struct wl_listener *listener, *next; + + wl_list_for_each_safe(listener, next, &proxy->listener_list, link) + free(listener); + + wl_hash_table_remove(proxy->display->objects, proxy->object.id); + free(proxy); +} + +WL_EXPORT int +wl_proxy_add_listener(struct wl_proxy *proxy, + void (**implementation)(void), void *data) +{ + struct wl_listener *listener; + + listener = malloc(sizeof *listener); + if (listener == NULL) + return -1; + + listener->implementation = (void (**)(void)) implementation; + listener->data = data; + wl_list_insert(proxy->listener_list.prev, &listener->link); + + return 0; +} + +WL_EXPORT void +wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) +{ + struct wl_closure *closure; + va_list ap; + + va_start(ap, opcode); + closure = wl_connection_vmarshal(proxy->display->connection, + &proxy->object, opcode, ap, + &proxy->object.interface->methods[opcode]); + va_end(ap); + + wl_closure_send(closure, proxy->display->connection); + + if (wl_debug) { + fprintf(stderr, " -> "); + wl_closure_print(closure, &proxy->object); + } + + wl_closure_destroy(closure); +} + +static void +add_visual(struct wl_display *display, uint32_t id) +{ + struct wl_visual *visual; + + visual = (struct wl_visual *) + wl_proxy_create_for_id(display, &wl_visual_interface, id); + if (display->argb_visual == NULL) + display->argb_visual = visual; + else if (display->premultiplied_argb_visual == NULL) + display->premultiplied_argb_visual = visual; + else + display->rgb_visual = visual; +} + +WL_EXPORT struct wl_visual * +wl_display_get_argb_visual(struct wl_display *display) +{ + return display->argb_visual; +} + +WL_EXPORT struct wl_visual * +wl_display_get_premultiplied_argb_visual(struct wl_display *display) +{ + return display->premultiplied_argb_visual; +} + +WL_EXPORT struct wl_visual * +wl_display_get_rgb_visual(struct wl_display *display) +{ + return display->rgb_visual; +} + +static void +display_handle_invalid_object(void *data, + struct wl_display *display, uint32_t id) +{ + fprintf(stderr, "sent request to invalid object\n"); + abort(); +} + +static void +display_handle_invalid_method(void *data, + struct wl_display *display, + uint32_t id, uint32_t opcode) +{ + fprintf(stderr, "sent invalid request opcode\n"); + abort(); +} + +static void +display_handle_no_memory(void *data, + struct wl_display *display) +{ + fprintf(stderr, "server out of memory\n"); + abort(); +} + +static void +display_handle_global(void *data, + struct wl_display *display, + uint32_t id, const char *interface, uint32_t version) +{ + struct wl_global_listener *listener; + + if (strcmp(interface, "display") == 0) + wl_hash_table_insert(display->objects, + id, &display->proxy.object); + else if (strcmp(interface, "visual") == 0) + add_visual(display, id); + + wl_list_for_each(listener, &display->global_listener_list, link) + (*listener->handler)(display, + id, interface, version, listener->data); +} + +static void +display_handle_range(void *data, + struct wl_display *display, uint32_t range) +{ + display->next_range = range; +} + +static void +display_handle_key(void *data, + struct wl_display *display, uint32_t key, uint32_t time) +{ + struct wl_sync_handler *sync_handler; + struct wl_frame_handler *frame_handler; + + sync_handler = container_of(display->sync_list.next, + struct wl_sync_handler, link); + if (!wl_list_empty(&display->sync_list) && sync_handler->key == key) { + wl_list_remove(&sync_handler->link); + sync_handler->func(sync_handler->data); + free(sync_handler); + return; + } + + frame_handler = container_of(display->frame_list. next, + struct wl_frame_handler, link); + if (!wl_list_empty(&display->frame_list) && + frame_handler->key == key) { + wl_list_remove(&frame_handler->link); + frame_handler->func(frame_handler->data, time); + free(frame_handler); + return; + } + + fprintf(stderr, "unsolicited sync event, client gone?\n"); +} + +static const struct wl_display_listener display_listener = { + display_handle_invalid_object, + display_handle_invalid_method, + display_handle_no_memory, + display_handle_global, + display_handle_range, + display_handle_key +}; + +WL_EXPORT struct wl_display * +wl_display_connect(const char *name) +{ + struct wl_display *display; + struct sockaddr_un addr; + socklen_t size; + const char *runtime_dir; + const char *debug; + size_t name_size; + + debug = getenv("WAYLAND_DEBUG"); + if (debug) + wl_debug = 1; + + display = malloc(sizeof *display); + if (display == NULL) + return NULL; + + memset(display, 0, sizeof *display); + display->fd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (display->fd < 0) { + free(display); + return NULL; + } + + runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (runtime_dir == NULL) { + runtime_dir = "."; + fprintf(stderr, + "XDG_RUNTIME_DIR not set, falling back to %s\n", + runtime_dir); + } + + if (name == NULL) + name = getenv("WAYLAND_DISPLAY"); + if (name == NULL) + name = "wayland-0"; + + memset(&addr, 0, sizeof addr); + addr.sun_family = AF_LOCAL; + name_size = + snprintf(addr.sun_path, sizeof addr.sun_path, + "%s/%s", runtime_dir, name) + 1; + + size = offsetof (struct sockaddr_un, sun_path) + name_size; + + if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) { + close(display->fd); + free(display); + return NULL; + } + + display->objects = wl_hash_table_create(); + wl_list_init(&display->global_listener_list); + + display->proxy.object.interface = &wl_display_interface; + display->proxy.object.id = 1; + display->proxy.display = display; + wl_list_init(&display->proxy.listener_list); + + wl_list_init(&display->sync_list); + wl_list_init(&display->frame_list); + + display->listener.implementation = (void(**)(void)) &display_listener; + wl_list_insert(display->proxy.listener_list.prev, &display->listener.link); + + display->connection = wl_connection_create(display->fd, + connection_update, + display); + + return display; +} + +WL_EXPORT void +wl_display_destroy(struct wl_display *display) +{ + wl_connection_destroy(display->connection); + close(display->fd); + free(display); +} + +WL_EXPORT int +wl_display_get_fd(struct wl_display *display, + wl_display_update_func_t update, void *data) +{ + display->update = update; + display->update_data = data; + + display->update(display->mask, display->update_data); + + return display->fd; +} + +WL_EXPORT int +wl_display_sync_callback(struct wl_display *display, + wl_display_sync_func_t func, void *data) +{ + struct wl_sync_handler *handler; + + handler = malloc(sizeof *handler); + if (handler == NULL) + return -1; + + handler->func = func; + handler->key = display->key++; + handler->data = data; + + wl_list_insert(display->sync_list.prev, &handler->link); + wl_display_sync(display, handler->key); + + return 0; +} + +WL_EXPORT int +wl_display_frame_callback(struct wl_display *display, + wl_display_frame_func_t func, void *data) +{ + struct wl_frame_handler *handler; + + handler = malloc(sizeof *handler); + if (handler == NULL) + return -1; + + handler->func = func; + handler->key = display->key++; + handler->data = data; + + wl_list_insert(display->frame_list.prev, &handler->link); + wl_display_frame(display, handler->key); + + return 0; +} + +static void +handle_event(struct wl_display *display, + uint32_t id, uint32_t opcode, uint32_t size) +{ + uint32_t p[32]; + struct wl_listener *listener; + struct wl_proxy *proxy; + struct wl_closure *closure; + const struct wl_message *message; + + wl_connection_copy(display->connection, p, size); + if (id == 1) + proxy = &display->proxy; + else + proxy = wl_hash_table_lookup(display->objects, id); + + if (proxy == NULL) { + wl_connection_consume(display->connection, size); + return; + } + + message = &proxy->object.interface->events[opcode]; + closure = wl_connection_demarshal(display->connection, + size, display->objects, message); + + if (wl_debug) + wl_closure_print(closure, &proxy->object); + + wl_list_for_each(listener, &proxy->listener_list, link) + wl_closure_invoke(closure, &proxy->object, + listener->implementation[opcode], + listener->data); + + wl_closure_destroy(closure); +} + +WL_EXPORT void +wl_display_iterate(struct wl_display *display, uint32_t mask) +{ + uint32_t p[2], object, opcode, size; + int len; + + mask &= display->mask; + if (mask == 0) { + fprintf(stderr, + "wl_display_iterate called with unsolicited flags"); + return; + } + + len = wl_connection_data(display->connection, mask); + while (len > 0) { + if (len < sizeof p) + break; + + wl_connection_copy(display->connection, p, sizeof p); + object = p[0]; + opcode = p[1] & 0xffff; + size = p[1] >> 16; + if (len < size) + break; + + handle_event(display, object, opcode, size); + len -= size; + } + + if (len < 0) { + fprintf(stderr, "read error: %m\n"); + exit(EXIT_FAILURE); + } +} + +WL_EXPORT uint32_t +wl_display_allocate_id(struct wl_display *display) +{ + if (display->id_count == 0) { + display->id_count = 256; + display->id = display->next_range; + } + + display->id_count--; + + return display->id++; +} + +WL_EXPORT void +wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data) +{ + proxy->user_data = user_data; +} + +WL_EXPORT void * +wl_proxy_get_user_data(struct wl_proxy *proxy) +{ + return proxy->user_data; +} diff --git a/src/3rdparty/wayland/wayland-client.h b/src/3rdparty/wayland/wayland-client.h new file mode 100644 index 000000000..d207b0763 --- /dev/null +++ b/src/3rdparty/wayland/wayland-client.h @@ -0,0 +1,75 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _WAYLAND_CLIENT_H +#define _WAYLAND_CLIENT_H + +#include "wayland-util.h" +#include "wayland-client-protocol.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WL_DISPLAY_READABLE 0x01 +#define WL_DISPLAY_WRITABLE 0x02 + +typedef int (*wl_display_update_func_t)(uint32_t mask, void *data); +typedef void (*wl_display_sync_func_t)(void *data); +typedef void (*wl_display_frame_func_t)(void *data, uint32_t time); + +struct wl_display *wl_display_connect(const char *name); +void wl_display_destroy(struct wl_display *display); +int wl_display_get_fd(struct wl_display *display, + wl_display_update_func_t update, void *data); +uint32_t wl_display_allocate_id(struct wl_display *display); +void wl_display_iterate(struct wl_display *display, uint32_t mask); +int wl_display_sync_callback(struct wl_display *display, + wl_display_sync_func_t func, void *data); +int wl_display_frame_callback(struct wl_display *display, + wl_display_frame_func_t func, void *data); + +struct wl_global_listener; +typedef void (*wl_display_global_func_t)(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, + void *data); +void +wl_display_remove_global_listener(struct wl_display *display, + struct wl_global_listener *listener); + +struct wl_global_listener * +wl_display_add_global_listener(struct wl_display *display, + wl_display_global_func_t handler, void *data); +struct wl_visual * +wl_display_get_argb_visual(struct wl_display *display); +struct wl_visual * +wl_display_get_premultiplied_argb_visual(struct wl_display *display); +struct wl_visual * +wl_display_get_rgb_visual(struct wl_display *display); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland-egl.h b/src/3rdparty/wayland/wayland-egl.h new file mode 100644 index 000000000..d3de87c79 --- /dev/null +++ b/src/3rdparty/wayland/wayland-egl.h @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 Kristian Høgsberg + * Copyright © 2011 Benjamin Franzke + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _WAYLAND_EGL_H +#define _WAYLAND_EGL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <wayland-client.h> + +#define WL_EGL_PLATFORM 1 + +struct wl_egl_display; +struct wl_egl_window; +struct wl_egl_pixmap; + +struct wl_egl_display * +wl_egl_display_create(struct wl_display *egl_display); + +void +wl_egl_display_destroy(struct wl_egl_display *egl_display); + +struct wl_egl_window * +wl_egl_window_create(struct wl_egl_display *egl_display, + struct wl_surface *surface, + int width, int height, + struct wl_visual *visual); + +void +wl_egl_window_destroy(struct wl_egl_window *egl_window); + +void +wl_egl_window_resize(struct wl_egl_window *egl_window, + int width, int height, + int dx, int dy); + +void +wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, + int *width, int *height); + +struct wl_egl_pixmap * +wl_egl_pixmap_create(struct wl_egl_display *egl_display, + int width, int height, + struct wl_visual *visual, uint32_t flags); +void +wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap); + +struct wl_buffer * +wl_egl_pixmap_create_buffer(struct wl_egl_display *egl_display, + struct wl_egl_pixmap *egl_pixmap); + +void +wl_egl_pixmap_flush(struct wl_egl_display *egl_display, + struct wl_egl_pixmap *egl_pixmap); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland-hash.c b/src/3rdparty/wayland/wayland-hash.c new file mode 100644 index 000000000..b299a33da --- /dev/null +++ b/src/3rdparty/wayland/wayland-hash.c @@ -0,0 +1,296 @@ +/* + * Copyright © 2009 Intel Corporation + * Copyright © 1988-2004 Keith Packard and Bart Massey. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Except as contained in this notice, the names of the authors + * or their institutions shall not be used in advertising or + * otherwise to promote the sale, use or other dealings in this + * Software without prior written authorization from the + * authors. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * Keith Packard <keithp@keithp.com> + */ + +#include <stdlib.h> + +#include "wayland-util.h" + +struct hash_entry { + uint32_t hash; + void *data; +}; + +struct wl_hash_table { + struct hash_entry *table; + uint32_t size; + uint32_t rehash; + uint32_t max_entries; + uint32_t size_index; + uint32_t entries; + uint32_t deleted_entries; +}; + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +/* + * From Knuth -- a good choice for hash/rehash values is p, p-2 where + * p and p-2 are both prime. These tables are sized to have an extra 10% + * free to avoid exponential performance degradation as the hash table fills + */ + +static const uint32_t deleted_data; + +static const struct { + uint32_t max_entries, size, rehash; +} hash_sizes[] = { + { 2, 5, 3 }, + { 4, 7, 5 }, + { 8, 13, 11 }, + { 16, 19, 17 }, + { 32, 43, 41 }, + { 64, 73, 71 }, + { 128, 151, 149 }, + { 256, 283, 281 }, + { 512, 571, 569 }, + { 1024, 1153, 1151 }, + { 2048, 2269, 2267 }, + { 4096, 4519, 4517 }, + { 8192, 9013, 9011 }, + { 16384, 18043, 18041 }, + { 32768, 36109, 36107 }, + { 65536, 72091, 72089 }, + { 131072, 144409, 144407 }, + { 262144, 288361, 288359 }, + { 524288, 576883, 576881 }, + { 1048576, 1153459, 1153457 }, + { 2097152, 2307163, 2307161 }, + { 4194304, 4613893, 4613891 }, + { 8388608, 9227641, 9227639 }, + { 16777216, 18455029, 18455027 }, + { 33554432, 36911011, 36911009 }, + { 67108864, 73819861, 73819859 }, + { 134217728, 147639589, 147639587 }, + { 268435456, 295279081, 295279079 }, + { 536870912, 590559793, 590559791 }, + { 1073741824, 1181116273, 1181116271}, + { 2147483648ul, 2362232233ul, 2362232231ul} +}; + +static int +entry_is_free(struct hash_entry *entry) +{ + return entry->data == NULL; +} + +static int +entry_is_deleted(struct hash_entry *entry) +{ + return entry->data == &deleted_data; +} + +static int +entry_is_present(struct hash_entry *entry) +{ + return entry->data != NULL && entry->data != &deleted_data; +} + +WL_EXPORT struct wl_hash_table * +wl_hash_table_create(void) +{ + struct wl_hash_table *ht; + + ht = malloc(sizeof(*ht)); + if (ht == NULL) + return NULL; + + ht->size_index = 0; + ht->size = hash_sizes[ht->size_index].size; + ht->rehash = hash_sizes[ht->size_index].rehash; + ht->max_entries = hash_sizes[ht->size_index].max_entries; + ht->table = calloc(ht->size, sizeof(*ht->table)); + ht->entries = 0; + ht->deleted_entries = 0; + + if (ht->table == NULL) { + free(ht); + return NULL; + } + + return ht; +} + +/** + * Frees the given hash table. + */ +WL_EXPORT void +wl_hash_table_destroy(struct wl_hash_table *ht) +{ + if (!ht) + return; + + free(ht->table); + free(ht); +} + +/** + * Finds a hash table entry with the given key and hash of that key. + * + * Returns NULL if no entry is found. Note that the data pointer may be + * modified by the user. + */ +static void * +hash_table_search(struct wl_hash_table *ht, uint32_t hash) +{ + uint32_t hash_address; + + hash_address = hash % ht->size; + do { + uint32_t double_hash; + + struct hash_entry *entry = ht->table + hash_address; + + if (entry_is_free(entry)) { + return NULL; + } else if (entry_is_present(entry) && entry->hash == hash) { + return entry; + } + + double_hash = hash % ht->rehash; + if (double_hash == 0) + double_hash = 1; + + hash_address = (hash_address + double_hash) % ht->size; + } while (hash_address != hash % ht->size); + + return NULL; +} + +WL_EXPORT void * +wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash) +{ + struct hash_entry *entry; + + entry = hash_table_search(ht, hash); + if (entry != NULL) + return entry->data; + + return NULL; +} + +static void +hash_table_rehash(struct wl_hash_table *ht, int new_size_index) +{ + struct wl_hash_table old_ht; + struct hash_entry *table, *entry; + + if (new_size_index >= ARRAY_SIZE(hash_sizes)) + return; + + table = calloc(hash_sizes[new_size_index].size, sizeof(*ht->table)); + if (table == NULL) + return; + + old_ht = *ht; + + ht->table = table; + ht->size_index = new_size_index; + ht->size = hash_sizes[ht->size_index].size; + ht->rehash = hash_sizes[ht->size_index].rehash; + ht->max_entries = hash_sizes[ht->size_index].max_entries; + ht->entries = 0; + ht->deleted_entries = 0; + + for (entry = old_ht.table; + entry != old_ht.table + old_ht.size; + entry++) { + if (entry_is_present(entry)) { + wl_hash_table_insert(ht, entry->hash, entry->data); + } + } + + free(old_ht.table); +} + +/** + * Inserts the data with the given hash into the table. + * + * Note that insertion may rearrange the table on a resize or rehash, + * so previously found hash_entries are no longer valid after this function. + */ +WL_EXPORT int +wl_hash_table_insert(struct wl_hash_table *ht, uint32_t hash, void *data) +{ + uint32_t hash_address; + + if (ht->entries >= ht->max_entries) { + hash_table_rehash(ht, ht->size_index + 1); + } else if (ht->deleted_entries + ht->entries >= ht->max_entries) { + hash_table_rehash(ht, ht->size_index); + } + + hash_address = hash % ht->size; + do { + struct hash_entry *entry = ht->table + hash_address; + uint32_t double_hash; + + if (!entry_is_present(entry)) { + if (entry_is_deleted(entry)) + ht->deleted_entries--; + entry->hash = hash; + entry->data = data; + ht->entries++; + return 0; + } + + double_hash = hash % ht->rehash; + if (double_hash == 0) + double_hash = 1; + + hash_address = (hash_address + double_hash) % ht->size; + } while (hash_address != hash % ht->size); + + /* We could hit here if a required resize failed. An unchecked-malloc + * application could ignore this result. + */ + return -1; +} + +/** + * This function deletes the given hash table entry. + * + * Note that deletion doesn't otherwise modify the table, so an iteration over + * the table deleting entries is safe. + */ +WL_EXPORT void +wl_hash_table_remove(struct wl_hash_table *ht, uint32_t hash) +{ + struct hash_entry *entry; + + entry = hash_table_search(ht, hash); + if (entry != NULL) { + entry->data = (void *) &deleted_data; + ht->entries--; + ht->deleted_entries++; + } +} diff --git a/src/3rdparty/wayland/wayland-protocol.c b/src/3rdparty/wayland/wayland-protocol.c new file mode 100644 index 000000000..1b00ac44c --- /dev/null +++ b/src/3rdparty/wayland/wayland-protocol.c @@ -0,0 +1,228 @@ +/* + * Copyright © 2010 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + +#include <stdlib.h> +#include <stdint.h> +#include "wayland-util.h" + +static const struct wl_message display_requests[] = { + { "sync", "u" }, + { "frame", "u" }, +}; + +static const struct wl_message display_events[] = { + { "invalid_object", "u" }, + { "invalid_method", "uu" }, + { "no_memory", "" }, + { "global", "nsu" }, + { "range", "u" }, + { "key", "uu" }, +}; + +WL_EXPORT const struct wl_interface wl_display_interface = { + "display", 1, + ARRAY_LENGTH(display_requests), display_requests, + ARRAY_LENGTH(display_events), display_events, +}; + +static const struct wl_message compositor_requests[] = { + { "create_surface", "n" }, +}; + +WL_EXPORT const struct wl_interface wl_compositor_interface = { + "compositor", 1, + ARRAY_LENGTH(compositor_requests), compositor_requests, + 0, NULL, +}; + +static const struct wl_message drm_requests[] = { + { "authenticate", "u" }, + { "create_buffer", "nuiiuo" }, +}; + +static const struct wl_message drm_events[] = { + { "device", "s" }, + { "authenticated", "" }, +}; + +WL_EXPORT const struct wl_interface wl_drm_interface = { + "drm", 1, + ARRAY_LENGTH(drm_requests), drm_requests, + ARRAY_LENGTH(drm_events), drm_events, +}; + +static const struct wl_message shm_requests[] = { + { "create_buffer", "nhiiuo" }, +}; + +WL_EXPORT const struct wl_interface wl_shm_interface = { + "shm", 1, + ARRAY_LENGTH(shm_requests), shm_requests, + 0, NULL, +}; + +static const struct wl_message buffer_requests[] = { + { "destroy", "" }, +}; + +WL_EXPORT const struct wl_interface wl_buffer_interface = { + "buffer", 1, + ARRAY_LENGTH(buffer_requests), buffer_requests, + 0, NULL, +}; + +static const struct wl_message shell_requests[] = { + { "move", "oou" }, + { "resize", "oouu" }, + { "create_drag", "n" }, + { "create_selection", "n" }, +}; + +static const struct wl_message shell_events[] = { + { "configure", "uuoii" }, +}; + +WL_EXPORT const struct wl_interface wl_shell_interface = { + "shell", 1, + ARRAY_LENGTH(shell_requests), shell_requests, + ARRAY_LENGTH(shell_events), shell_events, +}; + +static const struct wl_message selection_requests[] = { + { "offer", "s" }, + { "activate", "ou" }, + { "destroy", "" }, +}; + +static const struct wl_message selection_events[] = { + { "send", "sh" }, + { "cancelled", "" }, +}; + +WL_EXPORT const struct wl_interface wl_selection_interface = { + "selection", 1, + ARRAY_LENGTH(selection_requests), selection_requests, + ARRAY_LENGTH(selection_events), selection_events, +}; + +static const struct wl_message selection_offer_requests[] = { + { "receive", "sh" }, +}; + +static const struct wl_message selection_offer_events[] = { + { "offer", "s" }, + { "keyboard_focus", "o" }, +}; + +WL_EXPORT const struct wl_interface wl_selection_offer_interface = { + "selection_offer", 1, + ARRAY_LENGTH(selection_offer_requests), selection_offer_requests, + ARRAY_LENGTH(selection_offer_events), selection_offer_events, +}; + +static const struct wl_message drag_requests[] = { + { "offer", "s" }, + { "activate", "oou" }, + { "destroy", "" }, +}; + +static const struct wl_message drag_events[] = { + { "target", "s" }, + { "finish", "h" }, + { "reject", "" }, +}; + +WL_EXPORT const struct wl_interface wl_drag_interface = { + "drag", 1, + ARRAY_LENGTH(drag_requests), drag_requests, + ARRAY_LENGTH(drag_events), drag_events, +}; + +static const struct wl_message drag_offer_requests[] = { + { "accept", "us" }, + { "receive", "h" }, + { "reject", "" }, +}; + +static const struct wl_message drag_offer_events[] = { + { "offer", "s" }, + { "pointer_focus", "uoiiii" }, + { "motion", "uiiii" }, + { "drop", "" }, +}; + +WL_EXPORT const struct wl_interface wl_drag_offer_interface = { + "drag_offer", 1, + ARRAY_LENGTH(drag_offer_requests), drag_offer_requests, + ARRAY_LENGTH(drag_offer_events), drag_offer_events, +}; + +static const struct wl_message surface_requests[] = { + { "destroy", "" }, + { "attach", "oii" }, + { "map_toplevel", "" }, + { "map_transient", "oiiu" }, + { "map_fullscreen", "" }, + { "damage", "iiii" }, +}; + +WL_EXPORT const struct wl_interface wl_surface_interface = { + "surface", 1, + ARRAY_LENGTH(surface_requests), surface_requests, + 0, NULL, +}; + +static const struct wl_message input_device_requests[] = { + { "attach", "uoii" }, +}; + +static const struct wl_message input_device_events[] = { + { "motion", "uiiii" }, + { "button", "uuu" }, + { "key", "uuu" }, + { "pointer_focus", "uoiiii" }, + { "keyboard_focus", "uoa" }, +}; + +WL_EXPORT const struct wl_interface wl_input_device_interface = { + "input_device", 1, + ARRAY_LENGTH(input_device_requests), input_device_requests, + ARRAY_LENGTH(input_device_events), input_device_events, +}; + +static const struct wl_message output_events[] = { + { "geometry", "iiii" }, +}; + +WL_EXPORT const struct wl_interface wl_output_interface = { + "output", 1, + 0, NULL, + ARRAY_LENGTH(output_events), output_events, +}; + +WL_EXPORT const struct wl_interface wl_visual_interface = { + "visual", 1, + 0, NULL, + 0, NULL, +}; + diff --git a/src/3rdparty/wayland/wayland-server-protocol.h b/src/3rdparty/wayland/wayland-server-protocol.h new file mode 100644 index 000000000..8da6b7aa7 --- /dev/null +++ b/src/3rdparty/wayland/wayland-server-protocol.h @@ -0,0 +1,265 @@ +/* + * Copyright © 2010 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + +#ifndef WAYLAND_SERVER_PROTOCOL_H +#define WAYLAND_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stddef.h> +#include "wayland-util.h" + +struct wl_client; + +struct wl_display; +struct wl_compositor; +struct wl_drm; +struct wl_shm; +struct wl_buffer; +struct wl_shell; +struct wl_selection; +struct wl_selection_offer; +struct wl_drag; +struct wl_drag_offer; +struct wl_surface; +struct wl_input_device; +struct wl_output; +struct wl_visual; + +extern const struct wl_interface wl_display_interface; +extern const struct wl_interface wl_compositor_interface; +extern const struct wl_interface wl_drm_interface; +extern const struct wl_interface wl_shm_interface; +extern const struct wl_interface wl_buffer_interface; +extern const struct wl_interface wl_shell_interface; +extern const struct wl_interface wl_selection_interface; +extern const struct wl_interface wl_selection_offer_interface; +extern const struct wl_interface wl_drag_interface; +extern const struct wl_interface wl_drag_offer_interface; +extern const struct wl_interface wl_surface_interface; +extern const struct wl_interface wl_input_device_interface; +extern const struct wl_interface wl_output_interface; +extern const struct wl_interface wl_visual_interface; + +struct wl_display_interface { + void (*sync)(struct wl_client *client, + struct wl_display *display, + uint32_t key); + void (*frame)(struct wl_client *client, + struct wl_display *display, + uint32_t key); +}; + +#define WL_DISPLAY_INVALID_OBJECT 0 +#define WL_DISPLAY_INVALID_METHOD 1 +#define WL_DISPLAY_NO_MEMORY 2 +#define WL_DISPLAY_GLOBAL 3 +#define WL_DISPLAY_RANGE 4 +#define WL_DISPLAY_KEY 5 + +struct wl_compositor_interface { + void (*create_surface)(struct wl_client *client, + struct wl_compositor *compositor, + uint32_t id); +}; + +struct wl_drm_interface { + void (*authenticate)(struct wl_client *client, + struct wl_drm *drm, + uint32_t id); + void (*create_buffer)(struct wl_client *client, + struct wl_drm *drm, + uint32_t id, + uint32_t name, + int width, + int height, + uint32_t stride, + struct wl_visual *visual); +}; + +#define WL_DRM_DEVICE 0 +#define WL_DRM_AUTHENTICATED 1 + +struct wl_shm_interface { + void (*create_buffer)(struct wl_client *client, + struct wl_shm *shm, + uint32_t id, + int fd, + int width, + int height, + uint32_t stride, + struct wl_visual *visual); +}; + +struct wl_buffer_interface { + void (*destroy)(struct wl_client *client, + struct wl_buffer *buffer); +}; + +#ifndef WL_SHELL_RESIZE_ENUM +#define WL_SHELL_RESIZE_ENUM +enum wl_shell_resize { + WL_SHELL_RESIZE_NONE = 0, + WL_SHELL_RESIZE_TOP = 1, + WL_SHELL_RESIZE_BOTTOM = 2, + WL_SHELL_RESIZE_LEFT = 4, + WL_SHELL_RESIZE_TOP_LEFT = 5, + WL_SHELL_RESIZE_BOTTOM_LEFT = 6, + WL_SHELL_RESIZE_RIGHT = 8, + WL_SHELL_RESIZE_TOP_RIGHT = 9, + WL_SHELL_RESIZE_BOTTOM_RIGHT = 10, +}; +#endif /* WL_SHELL_RESIZE_ENUM */ + +struct wl_shell_interface { + void (*move)(struct wl_client *client, + struct wl_shell *shell, + struct wl_surface *surface, + struct wl_input_device *input_device, + uint32_t time); + void (*resize)(struct wl_client *client, + struct wl_shell *shell, + struct wl_surface *surface, + struct wl_input_device *input_device, + uint32_t time, + uint32_t edges); + void (*create_drag)(struct wl_client *client, + struct wl_shell *shell, + uint32_t id); + void (*create_selection)(struct wl_client *client, + struct wl_shell *shell, + uint32_t id); +}; + +#define WL_SHELL_CONFIGURE 0 + +struct wl_selection_interface { + void (*offer)(struct wl_client *client, + struct wl_selection *selection, + const char *type); + void (*activate)(struct wl_client *client, + struct wl_selection *selection, + struct wl_input_device *input_device, + uint32_t time); + void (*destroy)(struct wl_client *client, + struct wl_selection *selection); +}; + +#define WL_SELECTION_SEND 0 +#define WL_SELECTION_CANCELLED 1 + +struct wl_selection_offer_interface { + void (*receive)(struct wl_client *client, + struct wl_selection_offer *selection_offer, + const char *mime_type, + int fd); +}; + +#define WL_SELECTION_OFFER_OFFER 0 +#define WL_SELECTION_OFFER_KEYBOARD_FOCUS 1 + +struct wl_drag_interface { + void (*offer)(struct wl_client *client, + struct wl_drag *drag, + const char *type); + void (*activate)(struct wl_client *client, + struct wl_drag *drag, + struct wl_surface *surface, + struct wl_input_device *input_device, + uint32_t time); + void (*destroy)(struct wl_client *client, + struct wl_drag *drag); +}; + +#define WL_DRAG_TARGET 0 +#define WL_DRAG_FINISH 1 +#define WL_DRAG_REJECT 2 + +struct wl_drag_offer_interface { + void (*accept)(struct wl_client *client, + struct wl_drag_offer *drag_offer, + uint32_t time, + const char *type); + void (*receive)(struct wl_client *client, + struct wl_drag_offer *drag_offer, + int fd); + void (*reject)(struct wl_client *client, + struct wl_drag_offer *drag_offer); +}; + +#define WL_DRAG_OFFER_OFFER 0 +#define WL_DRAG_OFFER_POINTER_FOCUS 1 +#define WL_DRAG_OFFER_MOTION 2 +#define WL_DRAG_OFFER_DROP 3 + +struct wl_surface_interface { + void (*destroy)(struct wl_client *client, + struct wl_surface *surface); + void (*attach)(struct wl_client *client, + struct wl_surface *surface, + struct wl_buffer *buffer, + int x, + int y); + void (*map_toplevel)(struct wl_client *client, + struct wl_surface *surface); + void (*map_transient)(struct wl_client *client, + struct wl_surface *surface, + struct wl_surface *parent, + int x, + int y, + uint32_t flags); + void (*map_fullscreen)(struct wl_client *client, + struct wl_surface *surface); + void (*damage)(struct wl_client *client, + struct wl_surface *surface, + int x, + int y, + int width, + int height); +}; + +struct wl_input_device_interface { + void (*attach)(struct wl_client *client, + struct wl_input_device *input_device, + uint32_t time, + struct wl_buffer *buffer, + int hotspot_x, + int hotspot_y); +}; + +#define WL_INPUT_DEVICE_MOTION 0 +#define WL_INPUT_DEVICE_BUTTON 1 +#define WL_INPUT_DEVICE_KEY 2 +#define WL_INPUT_DEVICE_POINTER_FOCUS 3 +#define WL_INPUT_DEVICE_KEYBOARD_FOCUS 4 + +#define WL_OUTPUT_GEOMETRY 0 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland-server.c b/src/3rdparty/wayland/wayland-server.c new file mode 100644 index 000000000..dece0d1b2 --- /dev/null +++ b/src/3rdparty/wayland/wayland-server.c @@ -0,0 +1,726 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <dlfcn.h> +#include <assert.h> +#include <sys/time.h> +#include <ffi.h> + +#include "wayland-server.h" +#include "wayland-server-protocol.h" +#include "connection.h" + +struct wl_socket { + int fd; + struct sockaddr_un addr; + struct wl_list link; +}; + +struct wl_client { + struct wl_connection *connection; + struct wl_event_source *source; + struct wl_display *display; + struct wl_list resource_list; + uint32_t id_count; +}; + +struct wl_display { + struct wl_object object; + struct wl_event_loop *loop; + struct wl_hash_table *objects; + int run; + + struct wl_list frame_list; + uint32_t client_id_range; + uint32_t id; + + struct wl_list global_list; + struct wl_list socket_list; +}; + +struct wl_frame_listener { + struct wl_resource resource; + struct wl_client *client; + uint32_t key; + struct wl_list link; +}; + +struct wl_global { + struct wl_object *object; + wl_client_connect_func_t func; + struct wl_list link; +}; + +static int wl_debug = 0; + +WL_EXPORT void +wl_client_post_event(struct wl_client *client, struct wl_object *sender, + uint32_t opcode, ...) +{ + struct wl_closure *closure; + va_list ap; + + va_start(ap, opcode); + closure = wl_connection_vmarshal(client->connection, + sender, opcode, ap, + &sender->interface->events[opcode]); + va_end(ap); + + wl_closure_send(closure, client->connection); + + if (wl_debug) { + fprintf(stderr, " -> "); + wl_closure_print(closure, sender); + } + + wl_closure_destroy(closure); +} + +static void +wl_client_connection_data(int fd, uint32_t mask, void *data) +{ + struct wl_client *client = data; + struct wl_connection *connection = client->connection; + struct wl_object *object; + struct wl_closure *closure; + const struct wl_message *message; + uint32_t p[2], opcode, size; + uint32_t cmask = 0; + int len; + + if (mask & WL_EVENT_READABLE) + cmask |= WL_CONNECTION_READABLE; + if (mask & WL_EVENT_WRITEABLE) + cmask |= WL_CONNECTION_WRITABLE; + + len = wl_connection_data(connection, cmask); + if (len < 0) { + wl_client_destroy(client); + return; + } + + while (len >= sizeof p) { + wl_connection_copy(connection, p, sizeof p); + opcode = p[1] & 0xffff; + size = p[1] >> 16; + if (len < size) + break; + + object = wl_hash_table_lookup(client->display->objects, p[0]); + if (object == NULL) { + wl_client_post_event(client, &client->display->object, + WL_DISPLAY_INVALID_OBJECT, p[0]); + wl_connection_consume(connection, size); + len -= size; + continue; + } + + if (opcode >= object->interface->method_count) { + wl_client_post_event(client, &client->display->object, + WL_DISPLAY_INVALID_METHOD, p[0], opcode); + wl_connection_consume(connection, size); + len -= size; + continue; + } + + message = &object->interface->methods[opcode]; + closure = wl_connection_demarshal(client->connection, size, + client->display->objects, + message); + len -= size; + + if (closure == NULL && errno == EINVAL) { + wl_client_post_event(client, &client->display->object, + WL_DISPLAY_INVALID_METHOD, + p[0], opcode); + continue; + } else if (closure == NULL && errno == ENOMEM) { + wl_client_post_no_memory(client); + continue; + } + + + if (wl_debug) + wl_closure_print(closure, object); + + wl_closure_invoke(closure, object, + object->implementation[opcode], client); + + wl_closure_destroy(closure); + } +} + +static int +wl_client_connection_update(struct wl_connection *connection, + uint32_t mask, void *data) +{ + struct wl_client *client = data; + uint32_t emask = 0; + + if (mask & WL_CONNECTION_READABLE) + emask |= WL_EVENT_READABLE; + if (mask & WL_CONNECTION_WRITABLE) + emask |= WL_EVENT_WRITEABLE; + + return wl_event_source_fd_update(client->source, emask); +} + +WL_EXPORT struct wl_display * +wl_client_get_display(struct wl_client *client) +{ + return client->display; +} + +static void +wl_display_post_range(struct wl_display *display, struct wl_client *client) +{ + wl_client_post_event(client, &client->display->object, + WL_DISPLAY_RANGE, display->client_id_range); + display->client_id_range += 256; + client->id_count += 256; +} + +static struct wl_client * +wl_client_create(struct wl_display *display, int fd) +{ + struct wl_client *client; + struct wl_global *global; + + client = malloc(sizeof *client); + if (client == NULL) + return NULL; + + memset(client, 0, sizeof *client); + client->display = display; + client->source = wl_event_loop_add_fd(display->loop, fd, + WL_EVENT_READABLE, + wl_client_connection_data, client); + client->connection = + wl_connection_create(fd, wl_client_connection_update, client); + + wl_list_init(&client->resource_list); + + wl_display_post_range(display, client); + + wl_list_for_each(global, &display->global_list, link) + wl_client_post_event(client, &client->display->object, + WL_DISPLAY_GLOBAL, + global->object, + global->object->interface->name, + global->object->interface->version); + + wl_list_for_each(global, &display->global_list, link) + if (global->func) + global->func(client, global->object); + + return client; +} + +WL_EXPORT void +wl_client_add_resource(struct wl_client *client, + struct wl_resource *resource) +{ + struct wl_display *display = client->display; + + if (client->id_count-- < 64) + wl_display_post_range(display, client); + + wl_hash_table_insert(client->display->objects, + resource->object.id, resource); + wl_list_insert(client->resource_list.prev, &resource->link); +} + +WL_EXPORT void +wl_client_post_no_memory(struct wl_client *client) +{ + wl_client_post_event(client, + &client->display->object, + WL_DISPLAY_NO_MEMORY); +} + +WL_EXPORT void +wl_client_post_global(struct wl_client *client, struct wl_object *object) +{ + wl_client_post_event(client, + &client->display->object, + WL_DISPLAY_GLOBAL, + object, + object->interface->name, + object->interface->version); +} + +WL_EXPORT void +wl_resource_destroy(struct wl_resource *resource, struct wl_client *client) +{ + struct wl_display *display = client->display; + + wl_list_remove(&resource->link); + if (resource->object.id > 0) + wl_hash_table_remove(display->objects, resource->object.id); + resource->destroy(resource, client); +} + +WL_EXPORT void +wl_client_destroy(struct wl_client *client) +{ + struct wl_resource *resource, *tmp; + + printf("disconnect from client %p\n", client); + + wl_list_for_each_safe(resource, tmp, &client->resource_list, link) + wl_resource_destroy(resource, client); + + wl_event_source_remove(client->source); + wl_connection_destroy(client->connection); + free(client); +} + +static void +lose_pointer_focus(struct wl_listener *listener, + struct wl_surface *surface, uint32_t time) +{ + struct wl_input_device *device = + container_of(listener, struct wl_input_device, + pointer_focus_listener); + + wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0); +} + +static void +lose_keyboard_focus(struct wl_listener *listener, + struct wl_surface *surface, uint32_t time) +{ + struct wl_input_device *device = + container_of(listener, struct wl_input_device, + keyboard_focus_listener); + + wl_input_device_set_keyboard_focus(device, NULL, time); +} + +WL_EXPORT void +wl_input_device_init(struct wl_input_device *device, + struct wl_compositor *compositor) +{ + wl_list_init(&device->pointer_focus_listener.link); + device->pointer_focus_listener.func = lose_pointer_focus; + wl_list_init(&device->keyboard_focus_listener.link); + device->keyboard_focus_listener.func = lose_keyboard_focus; + + device->x = 100; + device->y = 100; + device->compositor = compositor; +} + +WL_EXPORT void +wl_input_device_set_pointer_focus(struct wl_input_device *device, + struct wl_surface *surface, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy) +{ + if (device->pointer_focus == surface) + return; + + if (device->pointer_focus && + (!surface || device->pointer_focus->client != surface->client)) + wl_client_post_event(device->pointer_focus->client, + &device->object, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, NULL, 0, 0, 0, 0); + if (surface) + wl_client_post_event(surface->client, + &device->object, + WL_INPUT_DEVICE_POINTER_FOCUS, + time, surface, x, y, sx, sy); + + device->pointer_focus = surface; + device->pointer_focus_time = time; + + wl_list_remove(&device->pointer_focus_listener.link); + if (surface) + wl_list_insert(surface->destroy_listener_list.prev, + &device->pointer_focus_listener.link); +} + +WL_EXPORT void +wl_input_device_set_keyboard_focus(struct wl_input_device *device, + struct wl_surface *surface, + uint32_t time) +{ + if (device->keyboard_focus == surface) + return; + + if (device->keyboard_focus && + (!surface || device->keyboard_focus->client != surface->client)) + wl_client_post_event(device->keyboard_focus->client, + &device->object, + WL_INPUT_DEVICE_KEYBOARD_FOCUS, + time, NULL, &device->keys); + + if (surface) + wl_client_post_event(surface->client, + &device->object, + WL_INPUT_DEVICE_KEYBOARD_FOCUS, + time, surface, &device->keys); + + device->keyboard_focus = surface; + device->keyboard_focus_time = time; + + wl_list_remove(&device->keyboard_focus_listener.link); + if (surface) + wl_list_insert(surface->destroy_listener_list.prev, + &device->keyboard_focus_listener.link); +} + +WL_EXPORT void +wl_input_device_end_grab(struct wl_input_device *device, uint32_t time) +{ + const struct wl_grab_interface *interface; + + interface = device->grab->interface; + interface->end(device->grab, time); + device->grab->input_device = NULL; + device->grab = NULL; + + wl_list_remove(&device->grab_listener.link); +} + +static void +lose_grab_surface(struct wl_listener *listener, + struct wl_surface *surface, uint32_t time) +{ + struct wl_input_device *device = + container_of(listener, + struct wl_input_device, grab_listener); + + wl_input_device_end_grab(device, time); +} + +WL_EXPORT void +wl_input_device_start_grab(struct wl_input_device *device, + struct wl_grab *grab, + uint32_t button, uint32_t time) +{ + struct wl_surface *focus = device->pointer_focus; + + device->grab = grab; + device->grab_button = button; + device->grab_time = time; + device->grab_x = device->x; + device->grab_y = device->y; + + device->grab_listener.func = lose_grab_surface; + wl_list_insert(focus->destroy_listener_list.prev, + &device->grab_listener.link); + + grab->input_device = device; +} + +WL_EXPORT int +wl_input_device_update_grab(struct wl_input_device *device, + struct wl_grab *grab, + struct wl_surface *surface, uint32_t time) +{ + if (device->grab != &device->motion_grab || + device->grab_time != time || + device->pointer_focus != surface) + return -1; + + device->grab = grab; + grab->input_device = device; + + return 0; +} + +static void +display_sync(struct wl_client *client, + struct wl_display *display, uint32_t key) +{ + wl_client_post_event(client, &display->object, WL_DISPLAY_KEY, key, 0); +} + +static void +destroy_frame_listener(struct wl_resource *resource, struct wl_client *client) +{ + struct wl_frame_listener *listener = + container_of(resource, struct wl_frame_listener, resource); + + wl_list_remove(&listener->link); + free(listener); +} + +static void +display_frame(struct wl_client *client, + struct wl_display *display, uint32_t key) +{ + struct wl_frame_listener *listener; + + listener = malloc(sizeof *listener); + if (listener == NULL) { + wl_client_post_no_memory(client); + return; + } + + /* The listener is a resource so we destroy it when the client + * goes away. */ + listener->resource.destroy = destroy_frame_listener; + listener->resource.object.id = 0; + listener->client = client; + listener->key = key; + wl_list_insert(client->resource_list.prev, &listener->resource.link); + wl_list_insert(display->frame_list.prev, &listener->link); +} + +struct wl_display_interface display_interface = { + display_sync, + display_frame +}; + + +WL_EXPORT struct wl_display * +wl_display_create(void) +{ + struct wl_display *display; + const char *debug; + + debug = getenv("WAYLAND_DEBUG"); + if (debug) + wl_debug = 1; + + display = malloc(sizeof *display); + if (display == NULL) + return NULL; + + display->loop = wl_event_loop_create(); + if (display->loop == NULL) { + free(display); + return NULL; + } + + display->objects = wl_hash_table_create(); + if (display->objects == NULL) { + free(display); + return NULL; + } + + wl_list_init(&display->frame_list); + wl_list_init(&display->global_list); + wl_list_init(&display->socket_list); + + display->client_id_range = 256; /* Gah, arbitrary... */ + + display->id = 1; + display->object.interface = &wl_display_interface; + display->object.implementation = (void (**)(void)) &display_interface; + wl_display_add_object(display, &display->object); + if (wl_display_add_global(display, &display->object, NULL)) { + wl_event_loop_destroy(display->loop); + free(display); + return NULL; + } + + return display; +} + +WL_EXPORT void +wl_display_destroy(struct wl_display *display) +{ + struct wl_socket *s, *next; + + wl_event_loop_destroy(display->loop); + wl_hash_table_destroy(display->objects); + + wl_list_for_each_safe(s, next, &display->socket_list, link) { + close(s->fd); + unlink(s->addr.sun_path); + free(s); + } + + free(display); +} + +WL_EXPORT void +wl_display_add_object(struct wl_display *display, struct wl_object *object) +{ + object->id = display->id++; + wl_hash_table_insert(display->objects, object->id, object); +} + +WL_EXPORT int +wl_display_add_global(struct wl_display *display, + struct wl_object *object, wl_client_connect_func_t func) +{ + struct wl_global *global; + + global = malloc(sizeof *global); + if (global == NULL) + return -1; + + global->object = object; + global->func = func; + wl_list_insert(display->global_list.prev, &global->link); + + return 0; +} + +WL_EXPORT void +wl_display_post_frame(struct wl_display *display, uint32_t time) +{ + struct wl_frame_listener *listener, *next; + + wl_list_for_each_safe(listener, next, &display->frame_list, link) { + wl_client_post_event(listener->client, &display->object, + WL_DISPLAY_KEY, listener->key, time); + wl_resource_destroy(&listener->resource, listener->client); + } +} + +WL_EXPORT struct wl_event_loop * +wl_display_get_event_loop(struct wl_display *display) +{ + return display->loop; +} + +WL_EXPORT void +wl_display_terminate(struct wl_display *display) +{ + display->run = 0; +} + +WL_EXPORT void +wl_display_run(struct wl_display *display) +{ + display->run = 1; + + while (display->run) + wl_event_loop_dispatch(display->loop, -1); +} + +static void +socket_data(int fd, uint32_t mask, void *data) +{ + struct wl_display *display = data; + struct sockaddr_un name; + socklen_t length; + int client_fd; + + length = sizeof name; + client_fd = accept (fd, (struct sockaddr *) &name, &length); + if (client_fd < 0) + fprintf(stderr, "failed to accept\n"); + + wl_client_create(display, client_fd); +} + +WL_EXPORT int +wl_display_add_socket(struct wl_display *display, const char *name) +{ + struct wl_socket *s; + socklen_t size, name_size; + const char *runtime_dir; + + s = malloc(sizeof *s); + if (s == NULL) + return -1; + + s->fd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (s->fd < 0) + return -1; + + runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (runtime_dir == NULL) { + runtime_dir = "."; + fprintf(stderr, + "XDG_RUNTIME_DIR not set, falling back to %s\n", + runtime_dir); + } + + if (name == NULL) + name = getenv("WAYLAND_DISPLAY"); + if (name == NULL) + name = "wayland-0"; + + memset(&s->addr, 0, sizeof s->addr); + s->addr.sun_family = AF_LOCAL; + name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path, + "%s/%s", runtime_dir, name) + 1; + fprintf(stderr, "using socket %s\n", s->addr.sun_path); + + size = offsetof (struct sockaddr_un, sun_path) + name_size; + if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) + return -1; + + if (listen(s->fd, 1) < 0) + return -1; + + wl_event_loop_add_fd(display->loop, s->fd, + WL_EVENT_READABLE, + socket_data, display); + wl_list_insert(display->socket_list.prev, &s->link); + + return 0; +} + +WL_EXPORT int +wl_compositor_init(struct wl_compositor *compositor, + const struct wl_compositor_interface *interface, + struct wl_display *display) +{ + compositor->object.interface = &wl_compositor_interface; + compositor->object.implementation = (void (**)(void)) interface; + wl_display_add_object(display, &compositor->object); + if (wl_display_add_global(display, &compositor->object, NULL)) + return -1; + + compositor->argb_visual.object.interface = &wl_visual_interface; + compositor->argb_visual.object.implementation = NULL; + wl_display_add_object(display, &compositor->argb_visual.object); + wl_display_add_global(display, &compositor->argb_visual.object, NULL); + + compositor->premultiplied_argb_visual.object.interface = + &wl_visual_interface; + compositor->premultiplied_argb_visual.object.implementation = NULL; + wl_display_add_object(display, + &compositor->premultiplied_argb_visual.object); + wl_display_add_global(display, + &compositor->premultiplied_argb_visual.object, + NULL); + + compositor->rgb_visual.object.interface = &wl_visual_interface; + compositor->rgb_visual.object.implementation = NULL; + wl_display_add_object(display, + &compositor->rgb_visual.object); + wl_display_add_global(display, + &compositor->rgb_visual.object, NULL); + + return 0; +} diff --git a/src/3rdparty/wayland/wayland-server.h b/src/3rdparty/wayland/wayland-server.h new file mode 100644 index 000000000..f74cbae04 --- /dev/null +++ b/src/3rdparty/wayland/wayland-server.h @@ -0,0 +1,265 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef WAYLAND_H +#define WAYLAND_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include "wayland-util.h" +#include "wayland-server-protocol.h" + +enum { + WL_EVENT_READABLE = 0x01, + WL_EVENT_WRITEABLE = 0x02 +}; + +struct wl_event_loop; +struct wl_event_source; +typedef void (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data); +typedef void (*wl_event_loop_timer_func_t)(void *data); +typedef void (*wl_event_loop_signal_func_t)(int signal_number, void *data); +typedef void (*wl_event_loop_idle_func_t)(void *data); + +struct wl_event_loop *wl_event_loop_create(void); +void wl_event_loop_destroy(struct wl_event_loop *loop); +struct wl_event_source *wl_event_loop_add_fd(struct wl_event_loop *loop, + int fd, uint32_t mask, + wl_event_loop_fd_func_t func, + void *data); +int wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask); +struct wl_event_source *wl_event_loop_add_timer(struct wl_event_loop *loop, + wl_event_loop_timer_func_t func, + void *data); +struct wl_event_source * +wl_event_loop_add_signal(struct wl_event_loop *loop, + int signal_number, + wl_event_loop_signal_func_t func, + void *data); + +int wl_event_source_timer_update(struct wl_event_source *source, + int ms_delay); +int wl_event_source_remove(struct wl_event_source *source); + + +int wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout); +struct wl_event_source *wl_event_loop_add_idle(struct wl_event_loop *loop, + wl_event_loop_idle_func_t func, + void *data); +int wl_event_loop_get_fd(struct wl_event_loop *loop); + +struct wl_client; +struct wl_display; +struct wl_input_device; + +struct wl_display *wl_display_create(void); +void wl_display_destroy(struct wl_display *display); +struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); +int wl_display_add_socket(struct wl_display *display, const char *name); +void wl_display_terminate(struct wl_display *display); +void wl_display_run(struct wl_display *display); + +void wl_display_add_object(struct wl_display *display, struct wl_object *object); + +typedef void (*wl_client_connect_func_t)(struct wl_client *client, struct wl_object *global); + +int wl_display_add_global(struct wl_display *display, struct wl_object *object, wl_client_connect_func_t func); + +void wl_client_destroy(struct wl_client *client); +void wl_client_post_no_memory(struct wl_client *client); +void wl_client_post_global(struct wl_client *client, struct wl_object *object); + +struct wl_visual { + struct wl_object object; +}; + +struct wl_compositor { + struct wl_object object; + struct wl_visual argb_visual; + struct wl_visual premultiplied_argb_visual; + struct wl_visual rgb_visual; +}; + +struct wl_resource { + struct wl_object object; + void (*destroy)(struct wl_resource *resource, + struct wl_client *client); + struct wl_list link; +}; + +struct wl_buffer { + struct wl_resource resource; + struct wl_compositor *compositor; + struct wl_visual *visual; + int32_t width, height; + void (*attach)(struct wl_buffer *buffer, struct wl_surface *surface); + void (*damage)(struct wl_buffer *buffer, + struct wl_surface *surface, + int32_t x, int32_t y, int32_t width, int32_t height); +}; + +struct wl_listener { + struct wl_list link; + void (*func)(struct wl_listener *listener, + struct wl_surface *surface, uint32_t time); +}; + +struct wl_surface { + struct wl_resource resource; + struct wl_client *client; + struct wl_list destroy_listener_list; +}; + +struct wl_shell { + struct wl_object object; +}; + +struct wl_grab; +struct wl_grab_interface { + void (*motion)(struct wl_grab *grab, + uint32_t time, int32_t x, int32_t y); + void (*button)(struct wl_grab *grab, + uint32_t time, int32_t button, int32_t state); + void (*end)(struct wl_grab *grab, uint32_t time); +}; + +struct wl_grab { + const struct wl_grab_interface *interface; + struct wl_input_device *input_device; +}; + +struct wl_input_device { + struct wl_object object; + struct wl_compositor *compositor; + struct wl_surface *pointer_focus; + struct wl_surface *keyboard_focus; + struct wl_array keys; + uint32_t pointer_focus_time; + uint32_t keyboard_focus_time; + struct wl_listener pointer_focus_listener; + struct wl_listener keyboard_focus_listener; + + int32_t x, y; + struct wl_grab *grab; + struct wl_grab motion_grab; + uint32_t grab_time; + int32_t grab_x, grab_y; + uint32_t grab_button; + struct wl_listener grab_listener; +}; + +struct wl_drag_offer { + struct wl_object object; +}; + +struct wl_drag { + struct wl_resource resource; + struct wl_grab grab; + struct wl_drag_offer drag_offer; + struct wl_surface *source; + struct wl_surface *drag_focus; + struct wl_client *target; + int32_t x, y, sx, sy; + struct wl_array types; + const char *type; + uint32_t pointer_focus_time; + struct wl_listener drag_focus_listener; +}; + +struct wl_selection_offer { + struct wl_object object; +}; + +struct wl_selection { + struct wl_resource resource; + struct wl_client *client; + struct wl_input_device *input_device; + struct wl_selection_offer selection_offer; + struct wl_surface *selection_focus; + struct wl_client *target; + struct wl_array types; + struct wl_listener selection_focus_listener; +}; + +void +wl_client_post_event(struct wl_client *client, + struct wl_object *sender, + uint32_t event, ...); + +int +wl_display_set_compositor(struct wl_display *display, + struct wl_compositor *compositor, + const struct wl_compositor_interface *implementation); + +void +wl_display_post_frame(struct wl_display *display, uint32_t msecs); + +void +wl_client_add_resource(struct wl_client *client, + struct wl_resource *resource); + +struct wl_display * +wl_client_get_display(struct wl_client *client); + +void +wl_resource_destroy(struct wl_resource *resource, struct wl_client *client); + +void +wl_input_device_init(struct wl_input_device *device, + struct wl_compositor *compositor); + +void +wl_input_device_set_pointer_focus(struct wl_input_device *device, + struct wl_surface *surface, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + +void +wl_input_device_set_keyboard_focus(struct wl_input_device *device, + struct wl_surface *surface, + uint32_t time); + +void +wl_input_device_end_grab(struct wl_input_device *device, uint32_t time); +void +wl_input_device_start_grab(struct wl_input_device *device, + struct wl_grab *grab, + uint32_t button, uint32_t time); +int +wl_input_device_update_grab(struct wl_input_device *device, + struct wl_grab *grab, + struct wl_surface *surface, uint32_t time); + +int +wl_compositor_init(struct wl_compositor *compositor, + const struct wl_compositor_interface *interface, + struct wl_display *display); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland-util.c b/src/3rdparty/wayland/wayland-util.c new file mode 100644 index 000000000..364327433 --- /dev/null +++ b/src/3rdparty/wayland/wayland-util.c @@ -0,0 +1,123 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include "wayland-util.h" + +WL_EXPORT void +wl_list_init(struct wl_list *list) +{ + list->prev = list; + list->next = list; +} + +WL_EXPORT void +wl_list_insert(struct wl_list *list, struct wl_list *elm) +{ + elm->prev = list; + elm->next = list->next; + list->next = elm; + elm->next->prev = elm; +} + +WL_EXPORT void +wl_list_remove(struct wl_list *elm) +{ + elm->prev->next = elm->next; + elm->next->prev = elm->prev; +} + +WL_EXPORT int +wl_list_length(struct wl_list *list) +{ + struct wl_list *e; + int count; + + count = 0; + e = list->next; + while (e != list) { + e = e->next; + count++; + } + + return count; +} + +WL_EXPORT int +wl_list_empty(struct wl_list *list) +{ + return list->next == list; +} + +WL_EXPORT void +wl_array_init(struct wl_array *array) +{ + memset(array, 0, sizeof *array); +} + +WL_EXPORT void +wl_array_release(struct wl_array *array) +{ + free(array->data); +} + +WL_EXPORT void * +wl_array_add(struct wl_array *array, int size) +{ + int alloc; + void *data, *p; + + if (array->alloc > 0) + alloc = array->alloc; + else + alloc = 16; + + while (alloc < array->size + size) + alloc *= 2; + + if (array->alloc < alloc) { + if (array->alloc > 0) + data = realloc(array->data, alloc); + else + data = malloc(alloc); + + if (data == NULL) + return 0; + array->data = data; + array->alloc = alloc; + } + + p = array->data + array->size; + array->size += size; + + return p; +} + +WL_EXPORT void +wl_array_copy(struct wl_array *array, struct wl_array *source) +{ + array->size = 0; + wl_array_add(array, source->size); + memcpy(array->data, source->data, source->size); +} diff --git a/src/3rdparty/wayland/wayland-util.h b/src/3rdparty/wayland/wayland-util.h new file mode 100644 index 000000000..6c1231a99 --- /dev/null +++ b/src/3rdparty/wayland/wayland-util.h @@ -0,0 +1,157 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef WAYLAND_UTIL_H +#define WAYLAND_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> + +/* GCC visibility */ +#if defined(__GNUC__) && __GNUC__ >= 4 +#define WL_EXPORT __attribute__ ((visibility("default"))) +#else +#define WL_EXPORT +#endif + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +#define ALIGN(n, a) ( ((n) + ((a) - 1)) & ~((a) - 1) ) +#define DIV_ROUNDUP(n, a) ( ((n) + ((a) - 1)) / (a) ) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +struct wl_argument { + uint32_t type; + void *data; +}; + +struct wl_message { + const char *name; + const char *signature; + const void **types; +}; + +struct wl_interface { + const char *name; + int version; + int method_count; + const struct wl_message *methods; + int event_count; + const struct wl_message *events; +}; + +struct wl_object { + const struct wl_interface *interface; + void (**implementation)(void); + uint32_t id; +}; + +struct wl_hash_table; +struct wl_hash_table *wl_hash_table_create(void); +void wl_hash_table_destroy(struct wl_hash_table *ht); +void *wl_hash_table_lookup(struct wl_hash_table *ht, uint32_t hash); +int wl_hash_table_insert(struct wl_hash_table *ht, uint32_t hash, void *data); +void wl_hash_table_remove(struct wl_hash_table *ht, uint32_t hash); + +/** + * wl_list - linked list + * + * The list head is of "struct wl_list" type, and must be initialized + * using wl_list_init(). All entries in the list must be of the same + * type. The item type must have a "struct wl_list" member. This + * member will be initialized by wl_list_insert(). There is no need to + * call wl_list_init() on the individual item. To query if the list is + * empty in O(1), use wl_list_empty(). + * + * Let's call the list reference "struct wl_list foo_list", the item type as + * "item_t", and the item member as "struct wl_list link". The following code + * + * The following code will initialize a list: + * + * wl_list_init(foo_list); + * wl_list_insert(foo_list, item1); Pushes item1 at the head + * wl_list_insert(foo_list, item2); Pushes item2 at the head + * wl_list_insert(item2, item3); Pushes item3 after item2 + * + * The list now looks like [item2, item3, item1] + * + * Will iterate the list in ascending order: + * + * item_t *item; + * wl_list_for_each(item, foo_list, link) { + * Do_something_with_item(item); + * } + */ +struct wl_list { + struct wl_list *prev; + struct wl_list *next; +}; + +void wl_list_init(struct wl_list *list); +void wl_list_insert(struct wl_list *list, struct wl_list *elm); +void wl_list_remove(struct wl_list *elm); +int wl_list_length(struct wl_list *list); +int wl_list_empty(struct wl_list *list); + +#define __container_of(ptr, sample, member) \ + (void *)((char *)(ptr) - \ + ((char *)&(sample)->member - (char *)(sample))) + +#define wl_list_for_each(pos, head, member) \ + for (pos = 0, pos = __container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.next, pos, member)) + +#define wl_list_for_each_safe(pos, tmp, head, member) \ + for (pos = 0, tmp = 0, \ + pos = __container_of((head)->next, pos, member), \ + tmp = __container_of((pos)->member.next, tmp, member); \ + &pos->member != (head); \ + pos = tmp, \ + tmp = __container_of(pos->member.next, tmp, member)) + +#define wl_list_for_each_reverse(pos, head, member) \ + for (pos = 0, pos = __container_of((head)->prev, pos, member); \ + &pos->member != (head); \ + pos = __container_of(pos->member.prev, pos, member)) + +struct wl_array { + uint32_t size; + uint32_t alloc; + void *data; +}; + +void wl_array_init(struct wl_array *array); +void wl_array_release(struct wl_array *array); +void *wl_array_add(struct wl_array *array, int size); +void wl_array_copy(struct wl_array *array, struct wl_array *source); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/wayland/wayland.pro b/src/3rdparty/wayland/wayland.pro new file mode 100644 index 000000000..214ed9955 --- /dev/null +++ b/src/3rdparty/wayland/wayland.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS = client server |