[PATCH wayland v4 1/2] Add support for signed 24.8 decimal numbers

Daniel Stone daniel at fooishbar.org
Tue May 8 09:17:25 PDT 2012


'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 <daniel at fooishbar.org>
---
 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(-)

v4: Renamed to wl_fixed_t.
    Accessor functions changed to static inlines rather than macros.
    Simplified validate_demarshal_f test.

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 <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_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 <math.h>
 #include <stddef.h>
 #include <inttypes.h>
 
@@ -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 <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -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);
 }
 
-- 
1.7.10



More information about the wayland-devel mailing list