[RFC wayland] Track protocol object versions inside wl_proxy.

Jason Ekstrand jason at jlekstrand.net
Fri Nov 13 10:21:00 PST 2015


On Fri, Nov 13, 2015 at 3:18 AM, Giulio Camuffo <giuliocamuffo at gmail.com> wrote:
> So do i understand correctly that if the app creating the
> wl_compositor was built against a libwayland without this patch the
> version returned in mesa by wl_proxy_get_version() for every proxy
> will be always 1?

Yes, see also the second e-mail link below.  I proposed to make
wl_display version 0 so that libraries can detect whether the client
was built against old or new libwayland.

--Jason

> 2015-11-12 22:01 GMT+02:00 Derek Foreman <derekf at osg.samsung.com>:
>> From: Jason Ekstrand <jason at jlekstrand.net>
>>
>> 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
>> wayland-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list