[Mesa-dev] [PATCH 1/9] mesa: Make draw a first place driver method.

Brian Paul brianp at vmware.com
Tue Mar 20 15:16:18 UTC 2018


Maybe change the subject: "mesa: move vbo draw functions into 
dd_function_table"


On 03/15/2018 11:48 PM, Mathias.Froehlich at gmx.net wrote:
> From: Mathias Fröhlich <mathias.froehlich at web.de>
> 
> Make drawing functions members of struct dd_function_table.
> What if not drawing, should be the major purpose of an OpenGL
> driver.

I'm not sure I understand the comment.


> 
> Signed-off-by: Mathias Fröhlich <Mathias.Froehlich at web.de>
> ---
>   src/mesa/drivers/common/driverfuncs.c |  5 +++
>   src/mesa/main/dd.h                    | 81 +++++++++++++++++++++++++++++++++++
>   src/mesa/state_tracker/st_context.c   |  4 ++
>   src/mesa/vbo/vbo.h                    | 18 ++++++++
>   src/mesa/vbo/vbo_context.c            | 29 +++++++++++++
>   src/mesa/vbo/vbo_exec_array.c         | 39 ++++++-----------
>   src/mesa/vbo/vbo_exec_draw.c          | 11 ++---
>   src/mesa/vbo/vbo_primitive_restart.c  | 14 +++---
>   src/mesa/vbo/vbo_save_draw.c          |  9 +---
>   9 files changed, 162 insertions(+), 48 deletions(-)
> 
> diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
> index 8f2e3e075c..2ddfdb5efa 100644
> --- a/src/mesa/drivers/common/driverfuncs.c
> +++ b/src/mesa/drivers/common/driverfuncs.c
> @@ -55,6 +55,7 @@
>   #include "tnl/tnl.h"
>   #include "swrast/swrast.h"
>   #include "swrast/s_renderbuffer.h"
> +#include "vbo/vbo.h"
>   
>   #include "driverfuncs.h"
>   #include "meta.h"
> @@ -119,6 +120,10 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
>      /* ATI_fragment_shader */
>      driver->NewATIfs = NULL;
>   
> +   /* Draw functions */
> +   driver->Draw = _vbo_draw;
> +   driver->DrawIndirect = _vbo_draw_indirect;
> +
>      /* simple state commands */
>      driver->AlphaFunc = NULL;
>      driver->BlendColor = NULL;
> diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
> index 3e6a0418a2..09e9c41244 100644
> --- a/src/mesa/main/dd.h
> +++ b/src/mesa/main/dd.h
> @@ -51,6 +51,8 @@ struct gl_texture_image;
>   struct gl_texture_object;
>   struct gl_memory_info;
>   struct util_queue_monitoring;
> +struct _mesa_prim;
> +struct _mesa_index_buffer;
>   
>   /* GL_ARB_vertex_buffer_object */
>   /* Modifies GL_MAP_UNSYNCHRONIZED_BIT to allow driver to fail (return
> @@ -489,6 +491,85 @@ struct dd_function_table {
>                              struct gl_shader_program *shader);
>      /*@}*/
>   
> +
> +   /**
> +    * \name Draw functions.
> +    */
> +   /*@{*/
> +   /**
> +    * For indirect array drawing:
> +    *
> +    *    typedef struct {
> +    *       GLuint count;
> +    *       GLuint primCount;
> +    *       GLuint first;
> +    *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
> +    *    } DrawArraysIndirectCommand;
> +    *
> +    * For indirect indexed drawing:
> +    *
> +    *    typedef struct {
> +    *       GLuint count;
> +    *       GLuint primCount;
> +    *       GLuint firstIndex;
> +    *       GLint  baseVertex;
> +    *       GLuint baseInstance; // in GL 4.2 and later, must be zero otherwise
> +    *    } DrawElementsIndirectCommand;
> +    */
> +
> +   /**
> +    * Draw a number of primitives.
> +    * \param prims  array [nr_prims] describing what to draw (prim type,
> +    *               vertex count, first index, instance count, etc).
> +    * \param ib  index buffer for indexed drawing, NULL for array drawing
> +    * \param index_bounds_valid  are min_index and max_index valid?
> +    * \param min_index  lowest vertex index used
> +    * \param max_index  highest vertex index used
> +    * \param tfb_vertcount  if non-null, indicates which transform feedback
> +    *                       object has the vertex count.
> +    * \param tfb_stream  If called via DrawTransformFeedbackStream, specifies
> +    *                    the vertex stream buffer from which to get the vertex
> +    *                    count.
> +    * \param indirect  If any prims are indirect, this specifies the buffer
> +    *                  to find the "DrawArrays/ElementsIndirectCommand" data.
> +    *                  This may be deprecated in the future
> +    */
> +   void (*Draw)(struct gl_context *ctx,
> +                const struct _mesa_prim *prims, GLuint nr_prims,
> +                const struct _mesa_index_buffer *ib,
> +                GLboolean index_bounds_valid,
> +                GLuint min_index, GLuint max_index,
> +                struct gl_transform_feedback_object *tfb_vertcount,
> +                unsigned tfb_stream, struct gl_buffer_object *indirect);
> +
> +
> +   /**
> +    * Draw a primitive, getting the vertex count, instance count, start
> +    * vertex, etc. from a buffer object.
> +    * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
> +    * \param indirect_data  buffer to get "DrawArrays/ElementsIndirectCommand"
> +    *                       data
> +    * \param indirect_offset  offset of first primitive in indrect_data buffer
> +    * \param draw_count  number of primitives to draw
> +    * \param stride  stride, in bytes, between
> +    *                "DrawArrays/ElementsIndirectCommand" objects
> +    * \param indirect_draw_count_buffer  if non-NULL specifies a buffer to get
> +    *                                    the real draw_count value.  Used for
> +    *                                    GL_ARB_indirect_parameters.
> +    * \param indirect_draw_count_offset  offset to the draw_count value in
> +    *                                    indirect_draw_count_buffer
> +    * \param ib  index buffer for indexed drawing, NULL otherwise.
> +    */
> +   void (*DrawIndirect)(struct gl_context *ctx, GLuint mode,
> +                        struct gl_buffer_object *indirect_data,
> +                        GLsizeiptr indirect_offset, unsigned draw_count,
> +                        unsigned stride,
> +                        struct gl_buffer_object *indirect_draw_count_buffer,
> +                        GLsizeiptr indirect_draw_count_offset,
> +                        const struct _mesa_index_buffer *ib);
> +   /*@}*/
> +
> +
>      /**
>       * \name State-changing functions.
>       *
> diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
> index dfdd92f31b..b34fb29561 100644
> --- a/src/mesa/state_tracker/st_context.c
> +++ b/src/mesa/state_tracker/st_context.c
> @@ -749,6 +749,10 @@ st_init_driver_functions(struct pipe_screen *screen,
>      if (screen->get_param(screen, PIPE_CAP_STRING_MARKER))
>         functions->EmitStringMarker = st_emit_string_marker;
>   
> +   /* For now call through these into the vbo_set_draw_func... */
> +   functions->Draw = _vbo_draw;
> +   functions->DrawIndirect = _vbo_draw_indirect;
> +
>      functions->Enable = st_Enable;
>      functions->UpdateState = st_invalidate_state;
>      functions->QueryMemoryInfo = st_query_memory_info;
> diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
> index d6cf8e2afe..42436e0fac 100644
> --- a/src/mesa/vbo/vbo.h
> +++ b/src/mesa/vbo/vbo.h
> @@ -214,6 +214,24 @@ struct split_limits
>   };
>   
>   
> +void
> +_vbo_draw(struct gl_context *ctx, const struct _mesa_prim *prims,
> +               GLuint nr_prims, const struct _mesa_index_buffer *ib,
> +               GLboolean index_bounds_valid, GLuint min_index, GLuint max_index,
> +               struct gl_transform_feedback_object *tfb_vertcount,
> +               unsigned tfb_stream, struct gl_buffer_object *indirect);
> +
> +
> +void
> +_vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
> +                        struct gl_buffer_object *indirect_data,
> +                        GLsizeiptr indirect_offset, unsigned draw_count,
> +                        unsigned stride,
> +                        struct gl_buffer_object *indirect_draw_count_buffer,
> +                        GLsizeiptr indirect_draw_count_offset,
> +                        const struct _mesa_index_buffer *ib);
> +
> +
>   void
>   vbo_split_prims(struct gl_context *ctx,
>                   const struct gl_vertex_array *arrays,
> diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
> index acb28d0293..bef2b47fdf 100644
> --- a/src/mesa/vbo/vbo_context.c
> +++ b/src/mesa/vbo/vbo_context.c
> @@ -307,3 +307,32 @@ vbo_set_indirect_draw_func(struct gl_context *ctx,
>      struct vbo_context *vbo = vbo_context(ctx);
>      vbo->draw_indirect_prims = func;
>   }
> +
> +
> +void
> +_vbo_draw(struct gl_context *ctx, const struct _mesa_prim *prims,
> +               GLuint nr_prims, const struct _mesa_index_buffer *ib,
> +               GLboolean index_bounds_valid, GLuint min_index, GLuint max_index,
> +               struct gl_transform_feedback_object *tfb_vertcount,
> +               unsigned tfb_stream, struct gl_buffer_object *indirect)
> +{
> +   struct vbo_context *vbo = vbo_context(ctx);
> +   vbo->draw_prims(ctx, prims, nr_prims, ib, index_bounds_valid,
> +                   min_index, max_index, tfb_vertcount, tfb_stream, indirect);
> +}
> +
> +
> +void
> +_vbo_draw_indirect(struct gl_context *ctx, GLuint mode,
> +                        struct gl_buffer_object *indirect_data,
> +                        GLsizeiptr indirect_offset, unsigned draw_count,
> +                        unsigned stride,
> +                        struct gl_buffer_object *indirect_draw_count_buffer,
> +                        GLsizeiptr indirect_draw_count_offset,
> +                        const struct _mesa_index_buffer *ib)
> +{
> +   struct vbo_context *vbo = vbo_context(ctx);
> +   vbo->draw_indirect_prims(ctx, mode, indirect_data, indirect_offset,
> +                            draw_count, stride, indirect_draw_count_buffer,
> +                            indirect_draw_count_offset, ib);
> +}
> diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
> index 5029937336..18b0032ae8 100644
> --- a/src/mesa/vbo/vbo_exec_array.c
> +++ b/src/mesa/vbo/vbo_exec_array.c
> @@ -395,7 +395,6 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
>                   GLsizei count, GLuint numInstances, GLuint baseInstance,
>                   GLuint drawID)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_prim prim;
>   
>      if (skip_validated_draw(ctx))
> @@ -417,8 +416,8 @@ vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
>      prim.start = start;
>      prim.count = count;
>   
> -   vbo->draw_prims(ctx, &prim, 1, NULL,
> -                   GL_TRUE, start, start + count - 1, NULL, 0, NULL);
> +   ctx->Driver.Draw(ctx, &prim, 1, NULL,
> +                    GL_TRUE, start, start + count - 1, NULL, 0, NULL);
>   
>      if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
>         _mesa_flush(ctx);
> @@ -808,7 +807,6 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
>                                   GLint basevertex, GLuint numInstances,
>                                   GLuint baseInstance)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_index_buffer ib;
>      struct _mesa_prim prim;
>   
> @@ -872,8 +870,8 @@ vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
>       * for the latter case elsewhere.
>       */
>   
> -   vbo->draw_prims(ctx, &prim, 1, &ib,
> -                   index_bounds_valid, start, end, NULL, 0, NULL);
> +   ctx->Driver.Draw(ctx, &prim, 1, &ib,
> +                    index_bounds_valid, start, end, NULL, 0, NULL);
>   
>      if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
>         _mesa_flush(ctx);
> @@ -1237,7 +1235,6 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
>                                   const GLvoid * const *indices,
>                                   GLsizei primcount, const GLint *basevertex)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_index_buffer ib;
>      struct _mesa_prim *prim;
>      unsigned int index_type_size = sizeof_ib_type(type);
> @@ -1323,8 +1320,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
>               prim[i].basevertex = 0;
>         }
>   
> -      vbo->draw_prims(ctx, prim, primcount, &ib,
> -                      false, 0, ~0, NULL, 0, NULL);
> +      ctx->Driver.Draw(ctx, prim, primcount, &ib,
> +                       false, 0, ~0, NULL, 0, NULL);
>      }
>      else {
>         /* render one prim at a time */
> @@ -1353,7 +1350,7 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
>            else
>               prim[0].basevertex = 0;
>   
> -         vbo->draw_prims(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL);
> +         ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL);
>         }
>      }
>   
> @@ -1431,7 +1428,6 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
>                               struct gl_transform_feedback_object *obj,
>                               GLuint stream, GLuint numInstances)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_prim prim;
>   
>      if (_mesa_is_no_error_enabled(ctx)) {
> @@ -1477,7 +1473,7 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
>       * (like in DrawArrays), but we have no way to know how many vertices
>       * will be rendered. */
>   
> -   vbo->draw_prims(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL);
> +   ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL);
>   
>      if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
>         _mesa_flush(ctx);
> @@ -1561,11 +1557,9 @@ static void
>   vbo_validated_drawarraysindirect(struct gl_context *ctx,
>                                    GLenum mode, const GLvoid *indirect)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
> -
>      vbo_bind_arrays(ctx);
>   
> -   vbo->draw_indirect_prims(ctx, mode,
> +   ctx->Driver.DrawIndirect(ctx, mode,
>                               ctx->DrawIndirectBuffer, (GLsizeiptr) indirect,
>                               1 /* draw_count */ , 16 /* stride */ ,
>                               NULL, 0, NULL);
> @@ -1581,7 +1575,6 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
>                                         const GLvoid *indirect,
>                                         GLsizei primcount, GLsizei stride)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      GLsizeiptr offset = (GLsizeiptr) indirect;
>   
>      if (primcount == 0)
> @@ -1589,7 +1582,7 @@ vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
>   
>      vbo_bind_arrays(ctx);
>   
> -   vbo->draw_indirect_prims(ctx, mode, ctx->DrawIndirectBuffer, offset,
> +   ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset,
>                               primcount, stride, NULL, 0, NULL);
>   
>      if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
> @@ -1602,7 +1595,6 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx,
>                                      GLenum mode, GLenum type,
>                                      const GLvoid *indirect)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_index_buffer ib;
>   
>      vbo_bind_arrays(ctx);
> @@ -1612,7 +1604,7 @@ vbo_validated_drawelementsindirect(struct gl_context *ctx,
>      ib.obj = ctx->Array.VAO->IndexBufferObj;
>      ib.ptr = NULL;
>   
> -   vbo->draw_indirect_prims(ctx, mode,
> +   ctx->Driver.DrawIndirect(ctx, mode,
>                               ctx->DrawIndirectBuffer, (GLsizeiptr) indirect,
>                               1 /* draw_count */ , 20 /* stride */ ,
>                               NULL, 0, &ib);
> @@ -1628,7 +1620,6 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
>                                           const GLvoid *indirect,
>                                           GLsizei primcount, GLsizei stride)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_index_buffer ib;
>      GLsizeiptr offset = (GLsizeiptr) indirect;
>   
> @@ -1644,7 +1635,7 @@ vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
>      ib.obj = ctx->Array.VAO->IndexBufferObj;
>      ib.ptr = NULL;
>   
> -   vbo->draw_indirect_prims(ctx, mode,
> +   ctx->Driver.DrawIndirect(ctx, mode,
>                               ctx->DrawIndirectBuffer, offset,
>                               primcount, stride, NULL, 0, &ib);
>   
> @@ -1802,7 +1793,6 @@ vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx,
>                                              GLsizei maxdrawcount,
>                                              GLsizei stride)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      GLsizeiptr offset = indirect;
>   
>      if (maxdrawcount == 0)
> @@ -1810,7 +1800,7 @@ vbo_validated_multidrawarraysindirectcount(struct gl_context *ctx,
>   
>      vbo_bind_arrays(ctx);
>   
> -   vbo->draw_indirect_prims(ctx, mode,
> +   ctx->Driver.DrawIndirect(ctx, mode,
>                               ctx->DrawIndirectBuffer, offset,
>                               maxdrawcount, stride,
>                               ctx->ParameterBuffer, drawcount_offset, NULL);
> @@ -1828,7 +1818,6 @@ vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx,
>                                                GLsizei maxdrawcount,
>                                                GLsizei stride)
>   {
> -   struct vbo_context *vbo = vbo_context(ctx);
>      struct _mesa_index_buffer ib;
>      GLsizeiptr offset = (GLsizeiptr) indirect;
>   
> @@ -1844,7 +1833,7 @@ vbo_validated_multidrawelementsindirectcount(struct gl_context *ctx,
>      ib.obj = ctx->Array.VAO->IndexBufferObj;
>      ib.ptr = NULL;
>   
> -   vbo->draw_indirect_prims(ctx, mode,
> +   ctx->Driver.DrawIndirect(ctx, mode,
>                               ctx->DrawIndirectBuffer, offset,
>                               maxdrawcount, stride,
>                               ctx->ParameterBuffer, drawcount_offset, &ib);
> diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
> index d02b33c8ee..628720b1d0 100644
> --- a/src/mesa/vbo/vbo_exec_draw.c
> +++ b/src/mesa/vbo/vbo_exec_draw.c
> @@ -398,14 +398,9 @@ vbo_exec_vtx_flush(struct vbo_exec_context *exec, GLboolean keepUnmapped)
>               printf("%s %d %d\n", __func__, exec->vtx.prim_count,
>                      exec->vtx.vert_count);
>   
> -         vbo_context(ctx)->draw_prims(ctx,
> -                                      exec->vtx.prim,
> -                                      exec->vtx.prim_count,
> -                                      NULL,
> -                                      GL_TRUE,
> -                                      0,
> -                                      exec->vtx.vert_count - 1,
> -                                      NULL, 0, NULL);
> +         ctx->Driver.Draw(ctx, exec->vtx.prim, exec->vtx.prim_count,
> +                          NULL, GL_TRUE, 0, exec->vtx.vert_count - 1,
> +                          NULL, 0, NULL);
>   
>            /* Get new storage -- unless asked not to. */
>            if (!keepUnmapped)
> diff --git a/src/mesa/vbo/vbo_primitive_restart.c b/src/mesa/vbo/vbo_primitive_restart.c
> index 33ad37c573..699b566dca 100644
> --- a/src/mesa/vbo/vbo_primitive_restart.c
> +++ b/src/mesa/vbo/vbo_primitive_restart.c
> @@ -177,8 +177,6 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
>      GLuint sub_end_index;
>      GLuint restart_index = _mesa_primitive_restart_index(ctx, ib->index_size);
>      struct _mesa_prim temp_prim;
> -   struct vbo_context *vbo = vbo_context(ctx);
> -   vbo_draw_func draw_prims_func = vbo->draw_prims;
>      GLboolean map_ib = ib->obj->Name && !ib->obj->Mappings[MAP_INTERNAL].Pointer;
>      void *ptr;
>   
> @@ -249,13 +247,13 @@ vbo_sw_primitive_restart(struct gl_context *ctx,
>               temp_prim.count = MIN2(sub_end_index, end_index) - temp_prim.start;
>               if ((temp_prim.start == sub_prim->start) &&
>                   (temp_prim.count == sub_prim->count)) {
> -               draw_prims_func(ctx, &temp_prim, 1, ib,
> -                               GL_TRUE, sub_prim->min_index, sub_prim->max_index,
> -                               NULL, 0, NULL);
> +               ctx->Driver.Draw(ctx, &temp_prim, 1, ib, GL_TRUE,
> +                                sub_prim->min_index, sub_prim->max_index,
> +                                NULL, 0, NULL);
>               } else {
> -               draw_prims_func(ctx, &temp_prim, 1, ib,
> -                               GL_FALSE, -1, -1,
> -                               NULL, 0, NULL);
> +               ctx->Driver.Draw(ctx, &temp_prim, 1, ib,
> +                                GL_FALSE, -1, -1,
> +                                NULL, 0, NULL);
>               }
>            }
>            if (sub_end_index >= end_index) {
> diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
> index 69d28312d3..280e16cb81 100644
> --- a/src/mesa/vbo/vbo_save_draw.c
> +++ b/src/mesa/vbo/vbo_save_draw.c
> @@ -215,13 +215,8 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
>         if (node->vertex_count > 0) {
>            GLuint min_index = _vbo_save_get_min_index(node);
>            GLuint max_index = _vbo_save_get_max_index(node);
> -         vbo->draw_prims(ctx,
> -                         node->prims,
> -                         node->prim_count,
> -                         NULL,
> -                         GL_TRUE,
> -                         min_index, max_index,
> -                         NULL, 0, NULL);
> +         ctx->Driver.Draw(ctx, node->prims, node->prim_count, NULL, GL_TRUE,
> +                          min_index, max_index, NULL, 0, NULL);
>         }
>      }
>   
> 



More information about the mesa-dev mailing list