[Mesa-dev] [PATCH v3 2/2] gallium/winsys/kms: Add support for multi-planes

Tomasz Figa tfiga at chromium.org
Fri Mar 16 07:19:44 UTC 2018


On Wed, Mar 7, 2018 at 7:43 AM, Lepton Wu <lepton at chromium.org> wrote:
> Add a new struct kms_sw_plane which delegate a plane and use it
> in place of sw_displaytarget. Multiple planes share same underlying
> kms_sw_displaytarget.
>
> Change-Id: I0e9ca1d0ba0aa78c27dfdb50c30dc0c424fec172
> Signed-off-by: Lepton Wu <lepton at chromium.org>
> ---
>  .../winsys/sw/kms-dri/kms_dri_sw_winsys.c     | 162 +++++++++++++-----
>  1 file changed, 122 insertions(+), 40 deletions(-)
>
> diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
> index 30343222470..d191d5c4987 100644
> --- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
> +++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
> @@ -59,13 +59,22 @@
>  #define DEBUG_PRINT(msg, ...)
>  #endif
>
> +struct kms_sw_displaytarget;
>
> -struct kms_sw_displaytarget
> +struct kms_sw_plane
>  {
> -   enum pipe_format format;
>     unsigned width;
>     unsigned height;
>     unsigned stride;
> +   unsigned offset;
> +   int mapped;
> +   struct kms_sw_displaytarget *dt;
> +   struct list_head link;
> +};
> +
> +struct kms_sw_displaytarget
> +{
> +   enum pipe_format format;
>     unsigned size;
>
>     uint32_t handle;
> @@ -74,6 +83,7 @@ struct kms_sw_displaytarget
>
>     int ref_count;
>     struct list_head link;
> +   struct list_head planes;
>  };
>
>  struct kms_sw_winsys
> @@ -84,10 +94,16 @@ struct kms_sw_winsys
>     struct list_head bo_list;
>  };
>
> -static inline struct kms_sw_displaytarget *
> -kms_sw_displaytarget( struct sw_displaytarget *dt )
> +static inline struct kms_sw_plane *
> +kms_sw_plane( struct sw_displaytarget *dt )
>  {
> -   return (struct kms_sw_displaytarget *)dt;
> +   return (struct kms_sw_plane *)dt;
> +}
> +
> +static inline struct sw_displaytarget *
> +sw_displaytarget( struct kms_sw_plane *pl)
> +{
> +   return (struct sw_displaytarget *)pl;
>  }
>
>  static inline struct kms_sw_winsys *
> @@ -106,6 +122,39 @@ kms_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
>     return TRUE;
>  }
>
> +static struct kms_sw_plane *get_plane(struct kms_sw_displaytarget *kms_sw_dt,
> +                                      enum pipe_format format,
> +                                      unsigned width, unsigned height,
> +                                      unsigned stride, unsigned offset)
> +{
> +   struct kms_sw_plane *plane = NULL;
> +
> +   if (offset + util_format_get_2d_size(format, stride, height) >
> +       kms_sw_dt->size) {
> +      DEBUG_PRINT("KMS-DEBUG: plane too big. format: %d stride: %d height: %d "
> +                  "offset: %d size:%d\n", format, stride, height, offset,
> +                  kms_sw_dt->size);
> +      return NULL;
> +   }
> +
> +   LIST_FOR_EACH_ENTRY(plane, &kms_sw_dt->planes, link) {
> +      if (plane->offset == offset)
> +         return plane;
> +   }
> +
> +   plane = CALLOC_STRUCT(kms_sw_plane);
> +   if (!plane)
> +      return NULL;
> +
> +   plane->width = width;
> +   plane->height = height;
> +   plane->stride = stride;
> +   plane->offset = offset;
> +   plane->dt = kms_sw_dt;
> +   list_add(&plane->link, &kms_sw_dt->planes);
> +   return plane;
> +}
> +
>  static struct sw_displaytarget *
>  kms_sw_displaytarget_create(struct sw_winsys *ws,
>                              unsigned tex_usage,
> @@ -125,11 +174,10 @@ kms_sw_displaytarget_create(struct sw_winsys *ws,
>     if (!kms_sw_dt)
>        goto no_dt;
>
> +   list_inithead(&kms_sw_dt->planes);
>     kms_sw_dt->ref_count = 1;
>
>     kms_sw_dt->format = format;
> -   kms_sw_dt->width = width;
> -   kms_sw_dt->height = height;
>
>     memset(&create_req, 0, sizeof(create_req));
>     create_req.bpp = 32;
> @@ -139,16 +187,19 @@ kms_sw_displaytarget_create(struct sw_winsys *ws,
>     if (ret)
>        goto free_bo;
>
> -   kms_sw_dt->stride = create_req.pitch;
>     kms_sw_dt->size = create_req.size;
>     kms_sw_dt->handle = create_req.handle;
> +   struct kms_sw_plane *plane = get_plane(kms_sw_dt, format, width, height,
> +                                          create_req.pitch, 0);
> +   if (!plane)
> +      goto free_bo;
>
>     list_add(&kms_sw_dt->link, &kms_sw->bo_list);
>
>     DEBUG_PRINT("KMS-DEBUG: created buffer %u (size %u)\n", kms_sw_dt->handle, kms_sw_dt->size);
>
> -   *stride = kms_sw_dt->stride;
> -   return (struct sw_displaytarget *)kms_sw_dt;
> +   *stride = create_req.pitch;
> +   return sw_displaytarget(plane);
>
>   free_bo:
>     memset(&destroy_req, 0, sizeof destroy_req);
> @@ -164,7 +215,8 @@ kms_sw_displaytarget_destroy(struct sw_winsys *ws,
>                               struct sw_displaytarget *dt)
>  {
>     struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws);
> -   struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt);
> +   struct kms_sw_plane *plane = kms_sw_plane(dt);
> +   struct kms_sw_displaytarget *kms_sw_dt = plane->dt;
>     struct drm_mode_destroy_dumb destroy_req;
>
>     kms_sw_dt->ref_count --;
> @@ -184,6 +236,11 @@ kms_sw_displaytarget_destroy(struct sw_winsys *ws,
>
>     DEBUG_PRINT("KMS-DEBUG: destroyed buffer %u\n", kms_sw_dt->handle);
>
> +   struct kms_sw_plane *tmp;
> +   LIST_FOR_EACH_ENTRY_SAFE(plane, tmp, &kms_sw_dt->planes, link) {
> +      FREE(plane);
> +   }
> +
>     FREE(kms_sw_dt);
>  }
>
> @@ -193,7 +250,8 @@ kms_sw_displaytarget_map(struct sw_winsys *ws,
>                           unsigned flags)
>  {
>     struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws);
> -   struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt);
> +   struct kms_sw_plane *plane = kms_sw_plane(dt);
> +   struct kms_sw_displaytarget *kms_sw_dt = plane->dt;
>     struct drm_mode_map_dumb map_req;
>     int prot, ret;
>
> @@ -216,7 +274,8 @@ kms_sw_displaytarget_map(struct sw_winsys *ws,
>     DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n",
>           kms_sw_dt->handle, kms_sw_dt->size, *ptr);
>
> -   return *ptr;
> +   plane->mapped = 1;

If we refcount the mapping, we would just increment the mapping
refcount here instead and plane->mapped field wouldn't be necessary.

> +   return *ptr + plane->offset;
>  }
>
>  static struct kms_sw_displaytarget *
> @@ -239,10 +298,11 @@ kms_sw_displaytarget_find_and_ref(struct kms_sw_winsys *kms_sw,
>     return NULL;
>  }
>
> -static struct kms_sw_displaytarget *
> +static struct kms_sw_plane *
>  kms_sw_displaytarget_add_from_prime(struct kms_sw_winsys *kms_sw, int fd,
> +                                    enum pipe_format format,
>                                      unsigned width, unsigned height,
> -                                    unsigned stride)
> +                                    unsigned stride, unsigned offset)
>  {
>     uint32_t handle = -1;
>     struct kms_sw_displaytarget * kms_sw_dt;
> @@ -254,13 +314,19 @@ kms_sw_displaytarget_add_from_prime(struct kms_sw_winsys *kms_sw, int fd,
>        return NULL;
>
>     kms_sw_dt = kms_sw_displaytarget_find_and_ref(kms_sw, handle);
> -   if (kms_sw_dt)
> -      return kms_sw_dt;
> +   struct kms_sw_plane *plane = NULL;
> +   if (kms_sw_dt) {
> +      plane = get_plane(kms_sw_dt, format, width, height, stride, offset);
> +      if (!plane)
> +        kms_sw_dt->ref_count --;
> +      return plane;
> +   }
>
>     kms_sw_dt = CALLOC_STRUCT(kms_sw_displaytarget);
>     if (!kms_sw_dt)
>        return NULL;
>
> +   list_inithead(&kms_sw_dt->planes);
>     off_t lseek_ret = lseek(fd, 0, SEEK_END);
>     if (lseek_ret == -1) {
>        FREE(kms_sw_dt);
> @@ -269,22 +335,33 @@ kms_sw_displaytarget_add_from_prime(struct kms_sw_winsys *kms_sw, int fd,
>     kms_sw_dt->size = lseek_ret;
>     kms_sw_dt->ref_count = 1;
>     kms_sw_dt->handle = handle;
> -   kms_sw_dt->width = width;
> -   kms_sw_dt->height = height;
> -   kms_sw_dt->stride = stride;
>
>     lseek(fd, 0, SEEK_SET);
> +   plane = get_plane(kms_sw_dt, format, width, height, stride, offset);
> +   if (!plane) {
> +      FREE(kms_sw_dt);
> +      return NULL;
> +   }
>
>     list_add(&kms_sw_dt->link, &kms_sw->bo_list);
>
> -   return kms_sw_dt;
> +   return plane;
>  }
>
>  static void
>  kms_sw_displaytarget_unmap(struct sw_winsys *ws,
>                             struct sw_displaytarget *dt)
>  {
> -   struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt);
> +   struct kms_sw_plane *plane = kms_sw_plane(dt);
> +   struct kms_sw_displaytarget *kms_sw_dt = plane->dt;
> +
> +   plane->mapped = 0;
> +   LIST_FOR_EACH_ENTRY(plane, &kms_sw_dt->planes, link) {
> +      if (plane->mapped) {
> +         DEBUG_PRINT("KMS-DEBUG: ignore unmap buffer %u \n", kms_sw_dt->handle);
> +         return;
> +      }
> +   }

This would be greatly simplified with mapping refcounting. We wouldn't
need to iterate through the list of planes. Just decrement the counter
and really unmap only if it goes to 0.

Best regards,
Tomasz


More information about the mesa-dev mailing list