[Mesa-dev] [PATCH] gallium/winsys/kms: Add support for multi-planes (v2)
Tomasz Figa
tfiga at chromium.org
Tue Jan 9 09:15:44 UTC 2018
Adding some folks on CC for broader distribution.
On Tue, Jan 9, 2018 at 3:52 PM, Lepton Wu <lepton at chromium.org> wrote:
> 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