From: Jason Ekstrand <[email protected]>

This provides a standardized mechanism for tracking protocol object
versions in client code.  The wl_display object is created with version 1.
Every time an object is created from within wl_registry_bind, it gets the
bound version.  Every other time an object is created, it simply inherits
it's version from the parent object that created it.

---
Sooo, seems to finally fix the EGLSwapBuffersWithDamage problem, we also
need this patch.  However, it's not complete.

I've rebased it and updated it.  Here's the original posting:
http://lists.freedesktop.org/archives/wayland-devel/2014-April/014004.html

Of special importance is:
http://lists.freedesktop.org/archives/wayland-devel/2014-April/014011.html

And the proposed solution to the new backwards compatibility issue.  If we
get a consensus on a way forward, I can pick this up and finish it off...

 src/scanner.c             |  29 ++++++++----
 src/wayland-client-core.h |  14 ++++++
 src/wayland-client.c      | 112 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 140 insertions(+), 15 deletions(-)

diff --git a/src/scanner.c b/src/scanner.c
index 8ecdd56..850e72a 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -889,6 +889,14 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
               interface->name, interface->name, interface->name,
               interface->name);
 
+       printf("static inline uint32_t\n"
+              "%s_get_version(struct %s *%s)\n"
+              "{\n"
+              "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n"
+              "}\n\n",
+              interface->name, interface->name, interface->name,
+              interface->name);
+
        has_destructor = 0;
        has_destroy = 0;
        wl_list_for_each(m, message_list, link) {
@@ -960,20 +968,25 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
 
                printf(")\n"
                       "{\n");
-               if (ret) {
+               if (ret && ret->interface_name == NULL) {
                        printf("\tstruct wl_proxy *%s;\n\n"
-                              "\t%s = wl_proxy_marshal_constructor("
+                              "\t%s = wl_proxy_marshal_constructor_versioned("
                               "(struct wl_proxy *) %s,\n"
-                              "\t\t\t %s_%s, ",
+                              "\t\t\t %s_%s, interface, version",
                               ret->name, ret->name,
                               interface->name,
                               interface->uppercase_name,
                               m->uppercase_name);
-
-                       if (ret->interface_name == NULL)
-                               printf("interface");
-                       else
-                               printf("&%s_interface", ret->interface_name);
+               } else if (ret) {
+                       printf("\tstruct wl_proxy *%s;\n\n"
+                              "\t%s = wl_proxy_marshal_constructor("
+                              "(struct wl_proxy *) %s,\n"
+                              "\t\t\t %s_%s, &%s_interface",
+                              ret->name, ret->name,
+                              interface->name,
+                              interface->uppercase_name,
+                              m->uppercase_name,
+                              ret->interface_name);
                } else {
                        printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
                               "\t\t\t %s_%s",
diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h
index 8b4b4b8..ed41773 100644
--- a/src/wayland-client-core.h
+++ b/src/wayland-client-core.h
@@ -138,10 +138,21 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy,
                             const struct wl_interface *interface,
                             ...);
 
+struct wl_proxy *wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
+                                                       uint32_t opcode,
+                                                       const struct 
wl_interface *interface,
+                                                       uint32_t version,
+                                                       ...);
 struct wl_proxy *
 wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
                                   uint32_t opcode, union wl_argument *args,
                                   const struct wl_interface *interface);
+struct wl_proxy *
+wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
+                                            uint32_t opcode,
+                                            union wl_argument *args,
+                                            const struct wl_interface 
*interface,
+                                            uint32_t version);
 
 void
 wl_proxy_destroy(struct wl_proxy *proxy);
@@ -165,6 +176,9 @@ void *
 wl_proxy_get_user_data(struct wl_proxy *proxy);
 
 uint32_t
+wl_proxy_get_version(struct wl_proxy *proxy);
+
+uint32_t
 wl_proxy_get_id(struct wl_proxy *proxy);
 
 const char *
diff --git a/src/wayland-client.c b/src/wayland-client.c
index b1c600f..3fa342f 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -62,6 +62,7 @@ struct wl_proxy {
        int refcount;
        void *user_data;
        wl_dispatcher_func_t dispatcher;
+       uint32_t version;
 };
 
 struct wl_global {
@@ -326,7 +327,8 @@ wl_display_create_queue(struct wl_display *display)
 }
 
 static struct wl_proxy *
-proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
+proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
+            uint32_t version)
 {
        struct wl_proxy *proxy;
        struct wl_display *display = factory->display;
@@ -341,6 +343,7 @@ proxy_create(struct wl_proxy *factory, const struct 
wl_interface *interface)
        proxy->display = display;
        proxy->queue = factory->queue;
        proxy->refcount = 1;
+       proxy->version = version;
 
        proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
 
@@ -373,7 +376,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct 
wl_interface *interface)
        struct wl_proxy *proxy;
 
        pthread_mutex_lock(&display->mutex);
-       proxy = proxy_create(factory, interface);
+       proxy = proxy_create(factory, interface, factory->version);
        pthread_mutex_unlock(&display->mutex);
 
        return proxy;
@@ -398,6 +401,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
        proxy->display = display;
        proxy->queue = factory->queue;
        proxy->refcount = 1;
+       proxy->version = factory->version;
 
        wl_map_insert_at(&display->objects, 0, id, proxy);
 
@@ -529,7 +533,7 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy,
 static struct wl_proxy *
 create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
                      union wl_argument *args,
-                     const struct wl_interface *interface)
+                     const struct wl_interface *interface, uint32_t version)
 {
        int i, count;
        const char *signature;
@@ -543,7 +547,7 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct 
wl_message *message,
 
                switch (arg.type) {
                case 'n':
-                       new_proxy = proxy_create(proxy, interface);
+                       new_proxy = proxy_create(proxy, interface, version);
                        if (new_proxy == NULL)
                                return NULL;
 
@@ -568,7 +572,8 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct 
wl_message *message,
  *
  * For new-id arguments, this function will allocate a new wl_proxy
  * and send the ID to the server.  The new wl_proxy will be returned
- * on success or NULL on errror with errno set accordingly.
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will inherit their version from their parent.
  *
  * \note This is intended to be used by language bindings and not in
  * non-generated code.
@@ -582,6 +587,43 @@ wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
                                   uint32_t opcode, union wl_argument *args,
                                   const struct wl_interface *interface)
 {
+       return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
+                                                           args, interface,
+                                                           proxy->version);
+}
+
+
+/** Prepare a request to be sent to the compositor
+ *
+ * \param proxy The proxy object
+ * \param opcode Opcode of the request to be sent
+ * \param args Extra arguments for the given request
+ * \param interface The interface to use for the new proxy
+ * \param version The protocol object version for the new proxy
+ *
+ * Translates the request given by opcode and the extra arguments into the
+ * wire format and write it to the connection buffer.  This version takes an
+ * array of the union type wl_argument.
+ *
+ * For new-id arguments, this function will allocate a new wl_proxy
+ * and send the ID to the server.  The new wl_proxy will be returned
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will have the version specified.
+ *
+ * \note This is intended to be used by language bindings and not in
+ * non-generated code.
+ *
+ * \sa wl_proxy_marshal()
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT struct wl_proxy *
+wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
+                                            uint32_t opcode,
+                                            union wl_argument *args,
+                                            const struct wl_interface 
*interface,
+                                            uint32_t version)
+{
        struct wl_closure *closure;
        struct wl_proxy *new_proxy = NULL;
        const struct wl_message *message;
@@ -591,7 +633,8 @@ wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
        message = &proxy->object.interface->methods[opcode];
        if (interface) {
                new_proxy = create_outgoing_proxy(proxy, message,
-                                                 args, interface);
+                                                 args, interface,
+                                                 version);
                if (new_proxy == NULL)
                        goto err_unlock;
        }
@@ -663,7 +706,8 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, 
...)
  *
  * For new-id arguments, this function will allocate a new wl_proxy
  * and send the ID to the server.  The new wl_proxy will be returned
- * on success or NULL on errror with errno set accordingly.
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will inherit their version from their parent.
  *
  * \note This should not normally be used by non-generated code.
  *
@@ -685,6 +729,46 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy, 
uint32_t opcode,
                                                  args, interface);
 }
 
+
+/** Prepare a request to be sent to the compositor
+ *
+ * \param proxy The proxy object
+ * \param opcode Opcode of the request to be sent
+ * \param interface The interface to use for the new proxy
+ * \param version The protocol object version of the new proxy
+ * \param ... Extra arguments for the given request
+ * \return A new wl_proxy for the new_id argument or NULL on error
+ *
+ * Translates the request given by opcode and the extra arguments into the
+ * wire format and write it to the connection buffer.
+ *
+ * For new-id arguments, this function will allocate a new wl_proxy
+ * and send the ID to the server.  The new wl_proxy will be returned
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will have the version specified.
+ *
+ * \note This should not normally be used by non-generated code.
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT struct wl_proxy *
+wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode,
+                                      const struct wl_interface *interface,
+                                      uint32_t version, ...)
+{
+       union wl_argument args[WL_CLOSURE_MAX_ARGS];
+       va_list ap;
+
+       va_start(ap, version);
+       
wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
+                                args, WL_CLOSURE_MAX_ARGS, ap);
+       va_end(ap);
+
+       return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
+                                                           args, interface,
+                                                           version);
+}
+
 /** Prepare a request to be sent to the compositor
  *
  * \param proxy The proxy object
@@ -848,6 +932,7 @@ wl_display_connect_to_fd(int fd)
        display->proxy.queue = &display->default_queue;
        display->proxy.flags = 0;
        display->proxy.refcount = 1;
+       display->proxy.version = 1;
 
        display->connection = wl_connection_create(display->fd);
        if (display->connection == NULL)
@@ -1839,6 +1924,19 @@ wl_proxy_get_user_data(struct wl_proxy *proxy)
        return proxy->user_data;
 }
 
+/** Get the protocol object version of a proxy object
+ *
+ * \param proxy The proxy object
+ * \return The protocol object version of the proxy
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT uint32_t
+wl_proxy_get_version(struct wl_proxy *proxy)
+{
+       return proxy->version;
+}
+
 /** Get the id of a proxy object
  *
  * \param proxy The proxy object
-- 
2.6.2

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

Reply via email to