[Mesa-dev] [PATCH] gallium/winsys/kms: Add support for multi-planes (v2)
Lepton Wu
lepton at chromium.org
Tue Jan 9 06:52:52 UTC 2018
Gentle ping. Thanks.
On Wed, Dec 27, 2017 at 11:35 PM, Lepton Wu <lepton at chromium.org> wrote:
> v2: address comments from Tomasz Figa
> a) Add more check for plane size.
> b) Avoid duplicated mapping and leaked mapping.
> c) Other minor changes.
>
> Signed-off-by: Lepton Wu <lepton at chromium.org>
>
> Change-Id: I0863f522976cc8863d6e95492d9346df35c066ec
> ---
> src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c | 179 +++++++++++++++-------
> 1 file changed, 126 insertions(+), 53 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 22e1c936ac5..69c05197081 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,20 +59,29 @@
> #define DEBUG_PRINT(msg, ...)
> #endif
>
> +struct kms_sw_displaytarget;
>
> -struct kms_sw_displaytarget
> -{
> - enum pipe_format format;
> +struct kms_sw_plane {
> unsigned width;
> unsigned height;
> unsigned stride;
> + unsigned offset;
> + struct kms_sw_displaytarget* dt;
> + struct list_head link;
> +};
> +
> +struct kms_sw_displaytarget
> +{
> + enum pipe_format format;
> unsigned size;
>
> uint32_t handle;
> void *mapped;
> + void *ro_mapped;
>
> int ref_count;
> struct list_head link;
> + struct list_head planes;
> };
>
> struct kms_sw_winsys
> @@ -83,10 +92,10 @@ 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 kms_sw_winsys *
> @@ -105,6 +114,42 @@ 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 * tmp, * 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(tmp, &kms_sw_dt->planes, link) {
> + if (tmp->offset == offset) {
> + plane = tmp;
> + break;
> + }
> + }
> + if (plane) {
> + assert(plane->width == width);
> + assert(plane->height == height);
> + assert(plane->stride == stride);
> + assert(plane->dt == kms_sw_dt);
> + } else {
> + plane = CALLOC_STRUCT(kms_sw_plane);
> + if (plane == NULL) 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,
> @@ -124,11 +169,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;
> @@ -138,17 +182,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 == NULL)
> + 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 (struct sw_displaytarget *) plane;
> free_bo:
> memset(&destroy_req, 0, sizeof destroy_req);
> destroy_req.handle = create_req.handle;
> @@ -163,13 +209,19 @@ 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 --;
> if (kms_sw_dt->ref_count > 0)
> return;
>
> + if (kms_sw_dt->ro_mapped)
> + munmap(kms_sw_dt->ro_mapped, kms_sw_dt->size);
> + if (kms_sw_dt->mapped)
> + munmap(kms_sw_dt->mapped, kms_sw_dt->size);
> +
> memset(&destroy_req, 0, sizeof destroy_req);
> destroy_req.handle = kms_sw_dt->handle;
> drmIoctl(kms_sw->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_req);
> @@ -178,6 +230,10 @@ 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);
> }
>
> @@ -187,7 +243,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;
>
> @@ -198,16 +255,20 @@ kms_sw_displaytarget_map(struct sw_winsys *ws,
> return NULL;
>
> prot = (flags == PIPE_TRANSFER_READ) ? PROT_READ : (PROT_READ | PROT_WRITE);
> - kms_sw_dt->mapped = mmap(0, kms_sw_dt->size, prot, MAP_SHARED,
> - kms_sw->fd, map_req.offset);
> -
> - if (kms_sw_dt->mapped == MAP_FAILED)
> - return NULL;
> + void **ptr = (flags == PIPE_TRANSFER_READ) ? &kms_sw_dt->ro_mapped : &kms_sw_dt->mapped;
> + if (*ptr == NULL) {
> + void * tmp = mmap(0, kms_sw_dt->size, prot, MAP_SHARED,
> + kms_sw->fd, map_req.offset);
> + if (tmp == MAP_FAILED)
> + return NULL;
> + *ptr = tmp;
> + }
>
> - DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p\n",
> - kms_sw_dt->handle, kms_sw_dt->size, kms_sw_dt->mapped);
> + DEBUG_PRINT("KMS-DEBUG: mapped buffer %u (size %u) at %p %dx%d \n",
> + kms_sw_dt->handle, kms_sw_dt->size, *ptr,
> + plane->width, plane->height);
>
> - return kms_sw_dt->mapped;
> + return *ptr + plane->offset;
> }
>
> static struct kms_sw_displaytarget *
> @@ -230,10 +291,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;
> @@ -245,13 +307,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 == NULL)
> + 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);
> @@ -260,27 +328,27 @@ 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 == NULL) {
> + 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;
>
> - DEBUG_PRINT("KMS-DEBUG: unmapped buffer %u (was %p)\n", kms_sw_dt->handle, kms_sw_dt->mapped);
> -
> - munmap(kms_sw_dt->mapped, kms_sw_dt->size);
> - kms_sw_dt->mapped = NULL;
> + DEBUG_PRINT("KMS-DEBUG: ignore unmap buffer %u \n", kms_sw_dt->handle);
> }
>
> static struct sw_displaytarget *
> @@ -291,30 +359,34 @@ kms_sw_displaytarget_from_handle(struct sw_winsys *ws,
> {
> struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws);
> struct kms_sw_displaytarget *kms_sw_dt;
> + struct kms_sw_plane *kms_sw_pl;
>
> assert(whandle->type == DRM_API_HANDLE_TYPE_KMS ||
> whandle->type == DRM_API_HANDLE_TYPE_FD);
>
> - if (whandle->offset != 0) {
> - DEBUG_PRINT("KMS-DEBUG: attempt to import unsupported winsys offset %d\n",
> - whandle->offset);
> - return NULL;
> - }
> -
> switch(whandle->type) {
> case DRM_API_HANDLE_TYPE_FD:
> - kms_sw_dt = kms_sw_displaytarget_add_from_prime(kms_sw, whandle->handle,
> + kms_sw_pl = kms_sw_displaytarget_add_from_prime(kms_sw, whandle->handle,
> + templ->format,
> templ->width0,
> templ->height0,
> - whandle->stride);
> - if (kms_sw_dt)
> - *stride = kms_sw_dt->stride;
> - return (struct sw_displaytarget *)kms_sw_dt;
> + whandle->stride,
> + whandle->offset);
> + if (kms_sw_pl) {
> + *stride = kms_sw_pl->stride;
> + }
> + return (struct sw_displaytarget *)kms_sw_pl;
> case DRM_API_HANDLE_TYPE_KMS:
> kms_sw_dt = kms_sw_displaytarget_find_and_ref(kms_sw, whandle->handle);
> if (kms_sw_dt) {
> - *stride = kms_sw_dt->stride;
> - return (struct sw_displaytarget *)kms_sw_dt;
> + struct kms_sw_plane * plane;
> + LIST_FOR_EACH_ENTRY(plane, &kms_sw_dt->planes, link) {
> + if (whandle->offset == plane->offset) {
> + *stride = plane->stride;
> + return (struct sw_displaytarget *)plane;
> + }
> + }
> + kms_sw_dt->ref_count --;
> }
> /* fallthrough */
> default:
> @@ -331,19 +403,20 @@ kms_sw_displaytarget_get_handle(struct sw_winsys *winsys,
> struct winsys_handle *whandle)
> {
> struct kms_sw_winsys *kms_sw = kms_sw_winsys(winsys);
> - 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;
>
> switch(whandle->type) {
> case DRM_API_HANDLE_TYPE_KMS:
> whandle->handle = kms_sw_dt->handle;
> - whandle->stride = kms_sw_dt->stride;
> - whandle->offset = 0;
> + whandle->stride = plane->stride;
> + whandle->offset = plane->offset;
> return TRUE;
> case DRM_API_HANDLE_TYPE_FD:
> if (!drmPrimeHandleToFD(kms_sw->fd, kms_sw_dt->handle,
> DRM_CLOEXEC, (int*)&whandle->handle)) {
> - whandle->stride = kms_sw_dt->stride;
> - whandle->offset = 0;
> + whandle->stride = plane->stride;
> + whandle->offset = plane->offset;
> return TRUE;
> }
> /* fallthrough */
> --
> 2.15.1.620.gb9897f4670-goog
>
More information about the mesa-dev
mailing list