From c5aba11accad178a81a373bd5d1de888b2a51101 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Tue, 8 May 2012 17:17:25 +0100 Subject: [PATCH] Add support for signed 24.8 decimal numbers 'fixed' is a signed decimal type which offers a sign bit, 23 bits of integer precision, and 8 bits of decimal precision. This is exposed as an opaque struct with conversion helpers to and from double and int on the C API side. Signed-off-by: Daniel Stone --- src/Makefile.am | 4 ++-- src/connection.c | 20 +++++++++++++++++++- src/scanner.c | 9 +++++++++ src/wayland-server.h | 1 + src/wayland-util.h | 24 ++++++++++++++++++++++++ tests/connection-test.c | 26 ++++++++++++++++++++++++++ 6 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index c685885..f93954e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ libwayland_util_la_SOURCES = \ wayland-os.h \ wayland-private.h -libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt +libwayland_server_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm libwayland_server_la_SOURCES = \ wayland-protocol.c \ wayland-server.c \ @@ -26,7 +26,7 @@ libwayland_server_la_SOURCES = \ data-device.c \ event-loop.c -libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt +libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-util.la -lrt -lm libwayland_client_la_SOURCES = \ wayland-protocol.c \ wayland-client.c diff --git a/src/connection.c b/src/connection.c index 06cc66f..a888940 100644 --- a/src/connection.c +++ b/src/connection.c @@ -22,6 +22,7 @@ #define _GNU_SOURCE +#include #include #include #include @@ -428,6 +429,13 @@ wl_closure_vmarshal(struct wl_closure *closure, for (i = 2; i < count; i++) { switch (message->signature[i - 2]) { + case 'f': + closure->types[i] = &ffi_type_sint32; + closure->args[i] = p; + if (end - p < 1) + goto err; + *p++ = va_arg(ap, wl_fixed_t); + break; case 'u': closure->types[i] = &ffi_type_uint32; closure->args[i] = p; @@ -611,6 +619,10 @@ wl_connection_demarshal(struct wl_connection *connection, closure->types[i] = &ffi_type_sint32; closure->args[i] = p++; break; + case 'f': + closure->types[i] = &ffi_type_sint32; + closure->args[i] = p++; + break; case 's': closure->types[i] = &ffi_type_pointer; length = *p++; @@ -812,6 +824,7 @@ void wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) { union wl_value *value; + int32_t si; int i; struct timespec tp; unsigned int time; @@ -835,7 +848,12 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send) fprintf(stderr, "%u", value->uint32); break; case 'i': - fprintf(stderr, "%d", value->uint32); + si = (int32_t) value->uint32; + fprintf(stderr, "%d", si); + break; + case 'f': + si = (int32_t) value->uint32; + fprintf(stderr, "%f", (double) si / 256.0); break; case 's': fprintf(stderr, "\"%s\"", value->string); diff --git a/src/scanner.c b/src/scanner.c index 45d67c7..e4797b0 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -83,6 +83,7 @@ enum arg_type { NEW_ID, INT, UNSIGNED, + FIXED, STRING, OBJECT, ARRAY, @@ -334,6 +335,8 @@ start_element(void *data, const char *element_name, const char **atts) arg->type = INT; else if (strcmp(type, "uint") == 0) arg->type = UNSIGNED; + else if (strcmp(type, "fixed") == 0) + arg->type = FIXED; else if (strcmp(type, "string") == 0) arg->type = STRING; else if (strcmp(type, "array") == 0) @@ -484,6 +487,9 @@ emit_type(struct arg *a) case UNSIGNED: printf("uint32_t "); break; + case FIXED: + printf("wl_fixed_t "); + break; case STRING: printf("const char *"); break; @@ -972,6 +978,9 @@ emit_messages(struct wl_list *message_list, case UNSIGNED: printf("u"); break; + case FIXED: + printf("f"); + break; case STRING: printf("s"); break; diff --git a/src/wayland-server.h b/src/wayland-server.h index ec4bd38..36356a2 100644 --- a/src/wayland-server.h +++ b/src/wayland-server.h @@ -281,6 +281,7 @@ struct wl_input_device { * The variable arguments' types are: * - type=uint: uint32_t * - type=int: int32_t + * - type=fixed: wl_fixed_t * - type=string: (const char *) to a nil-terminated string * - type=array: (struct wl_array *) * - type=fd: int, that is an open file descriptor diff --git a/src/wayland-util.h b/src/wayland-util.h index 1b8fd4b..8def7ee 100644 --- a/src/wayland-util.h +++ b/src/wayland-util.h @@ -27,6 +27,7 @@ extern "C" { #endif +#include #include #include @@ -165,6 +166,29 @@ void wl_array_release(struct wl_array *array); void *wl_array_add(struct wl_array *array, size_t size); void wl_array_copy(struct wl_array *array, struct wl_array *source); +typedef int32_t wl_fixed_t; +#define WL_FIXED_INVALID_VALUE ~0L + +static inline double wl_fixed_to_double(wl_fixed_t f) +{ + return (double) f / 256.0; +}; +static inline wl_fixed_t wl_fixed_from_double(double d) +{ + if (d >= (1 << 23)) + return WL_FIXED_INVALID_VALUE; + return (wl_fixed_t) round (d * 256.0); +}; + +static inline int wl_fixed_to_int(wl_fixed_t f) +{ + return f / 256; +} +static inline wl_fixed_t wl_fixed_from_int(int i) +{ + return wl_fixed_from_double(i); +} + #ifdef __cplusplus } #endif diff --git a/tests/connection-test.c b/tests/connection-test.c index 54ac423..14a58e6 100644 --- a/tests/connection-test.c +++ b/tests/connection-test.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include #include #include #include @@ -288,6 +289,13 @@ validate_demarshal_h(struct marshal_data *data, } static void +validate_demarshal_f(struct marshal_data *data, + struct wl_object *object, wl_fixed_t f) +{ + assert(data->value.i == f); +} + +static void demarshal(struct marshal_data *data, const char *format, uint32_t *msg, void (*func)(void)) { @@ -335,6 +343,12 @@ TEST(connection_demarshal) memcpy(&msg[3], data.value.s, msg[2]); demarshal(&data, "s", msg, (void *) validate_demarshal_s); + data.value.i = wl_fixed_from_double(-90000.2390); + msg[0] = 400200; + msg[1] = 12; + msg[2] = data.value.i; + demarshal(&data, "f", msg, (void *) validate_demarshal_f); + release_marshal_data(&data); } @@ -400,6 +414,18 @@ TEST(connection_marshal_demarshal) marshal_demarshal(&data, (void *) validate_demarshal_h, 8, "h", data.value.h); + data.value.i = wl_fixed_from_double(1234.5678); + marshal_demarshal(&data, (void *) validate_demarshal_f, + 12, "f", data.value.i); + + data.value.i = wl_fixed_from_double(-90000.2390); + marshal_demarshal(&data, (void *) validate_demarshal_f, + 12, "f", data.value.i); + + data.value.i = wl_fixed_from_double((1 << 23) - 1 + 0.0941); + marshal_demarshal(&data, (void *) validate_demarshal_f, + 12, "f", data.value.i); + release_marshal_data(&data); } -- 2.7.4