signed_24_8 is a signed decimal type which offers a sign bit, 23 bits of
integer precision, and 8 bits of decimal precision.  This is converted
to double on the C API side, as passing through varargs involves an
implicit type promotion to double anyway.

Signed-off-by: Daniel Stone <[email protected]>
---
 src/Makefile.am         |    4 ++--
 src/connection.c        |   20 +++++++++++++++++++-
 src/scanner.c           |    9 +++++++++
 src/wayland-server.h    |    1 +
 src/wayland-util.h      |    7 +++++++
 tests/connection-test.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 80 insertions(+), 3 deletions(-)

v3: Use a new typedef instead of double.

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..8d16dc4 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -22,6 +22,7 @@
 
 #define _GNU_SOURCE
 
+#include <math.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <string.h>
@@ -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_signed_24_8_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", wl_signed_24_8_to_double(si));
                        break;
                case 's':
                        fprintf(stderr, "\"%s\"", value->string);
diff --git a/src/scanner.c b/src/scanner.c
index 3fba0ad..a13b943 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -82,6 +82,7 @@ enum arg_type {
        NEW_ID,
        INT,
        UNSIGNED,
+       SIGNED_24_8,
        STRING,
        OBJECT,
        ARRAY,
@@ -296,6 +297,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, "signed_24_8") == 0)
+                       arg->type = SIGNED_24_8;
                else if (strcmp(type, "string") == 0)
                        arg->type = STRING;
                else if (strcmp(type, "array") == 0)
@@ -446,6 +449,9 @@ emit_type(struct arg *a)
        case UNSIGNED:
                printf("uint32_t ");
                break;
+       case SIGNED_24_8:
+               printf("wl_signed_24_8_t ");
+               break;
        case STRING:
                printf("const char *");
                break;
@@ -953,6 +959,9 @@ emit_messages(struct wl_list *message_list,
                        case UNSIGNED:
                                printf("u");
                                break;
+                       case SIGNED_24_8:
+                               printf("f");
+                               break;
                        case STRING:
                                printf("s");
                                break;
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 9d4f58e..73c6f57 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=signed_24_8: wl_signed_24_8_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..ebc60b5 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -165,6 +165,13 @@ 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_signed_24_8_t;
+#define wl_signed_24_8_to_double(x) ((double) (x) / 256.0)
+#define wl_signed_24_8_from_double(x) ((int32_t) round(x * 256.0))
+#define wl_signed_24_8_to_int(x) (x / 256)
+#define wl_signed_24_8_from_int(x) (x * 256)
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/tests/connection-test.c b/tests/connection-test.c
index 54ac423..608c7f6 100644
--- a/tests/connection-test.c
+++ b/tests/connection-test.c
@@ -20,6 +20,7 @@
  * OF THIS SOFTWARE.
  */
 
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -288,6 +289,17 @@ validate_demarshal_h(struct marshal_data *data,
 }
 
 static void
+validate_demarshal_f(struct marshal_data *data,
+                    struct wl_object *object, wl_signed_24_8_t f)
+{
+       double in = wl_signed_24_8_to_double(data->value.i);
+       double wire = wl_signed_24_8_to_double(f);
+
+       assert(data->value.i == f);
+       assert(fabs(in - wire) <= 1.0 / 256.0);
+}
+
+static void
 demarshal(struct marshal_data *data, const char *format,
          uint32_t *msg, void (*func)(void))
 {
@@ -335,6 +347,24 @@ TEST(connection_demarshal)
        memcpy(&msg[3], data.value.s, msg[2]);
        demarshal(&data, "s", msg, (void *) validate_demarshal_s);
 
+       data.value.i = wl_signed_24_8_from_double(5678.1234);
+       msg[0] = 400200;
+       msg[1] = 12;
+       msg[2] = data.value.i;
+       demarshal(&data, "f", msg, (void *) validate_demarshal_f);
+
+       data.value.i = wl_signed_24_8_from_double(-90000.2390);
+       msg[0] = 400200;
+       msg[1] = 12;
+       msg[2] = data.value.i;
+       demarshal(&data, "f", msg, (void *) validate_demarshal_f);
+
+       data.value.i = wl_signed_24_8_from_int((1 << 23) - 1);
+       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 +430,18 @@ TEST(connection_marshal_demarshal)
        marshal_demarshal(&data, (void *) validate_demarshal_h,
                          8, "h", data.value.h);
 
+       data.value.i = wl_signed_24_8_from_double(1234.5678);
+       marshal_demarshal(&data, (void *) validate_demarshal_f,
+                         12, "f", data.value.i);
+
+       data.value.i = wl_signed_24_8_from_double(-90000.2390);
+       marshal_demarshal(&data, (void *) validate_demarshal_f,
+                         12, "f", data.value.i);
+
+       data.value.i = wl_signed_24_8_from_double((1 << 23) - 1 + 0.0941);
+       marshal_demarshal(&data, (void *) validate_demarshal_f,
+                         12, "f", data.value.i);
+
        release_marshal_data(&data);
 }
 
-- 
1.7.10

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to