From f8606bd69655b5bfce053d80d6b9f7ead6e7f03f Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Mon, 19 Jun 2023 17:39:20 -0700 Subject: drm_fb: keep spare pages on a free list See previous commit re: mem_fb --- src/drm_fb.c | 124 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 50 deletions(-) diff --git a/src/drm_fb.c b/src/drm_fb.c index de43bd9..4996252 100644 --- a/src/drm_fb.c +++ b/src/drm_fb.c @@ -16,23 +16,24 @@ #include "til_util.h" /* drm fb backend, everything drm-specific in rototiller resides here. */ - -typedef struct drm_fb_t { - int drm_fd; - drmModeCrtc *crtc; - drmModeConnector *connector; - drmModeModeInfo *mode; -} drm_fb_t; - typedef struct drm_fb_page_t drm_fb_page_t; struct drm_fb_page_t { + drm_fb_page_t *next_spare; uint32_t *mmap; - size_t mmap_size; + size_t mmap_size, pitch; uint32_t drm_dumb_handle; uint32_t drm_fb_id; }; +typedef struct drm_fb_t { + int drm_fd; + drmModeCrtc *crtc; + drmModeConnector *connector; + drmModeModeInfo *mode; + drm_fb_page_t *spare_pages; +} drm_fb_t; + typedef struct drm_fb_setup_t { til_setup_t til_setup; const char *dev; @@ -425,12 +426,33 @@ _err: } +static void _drm_fb_page_free(drm_fb_t *fb, drm_fb_page_t *page) +{ + struct drm_mode_destroy_dumb destroy_dumb = {}; + + drmModeRmFB(fb->drm_fd, page->drm_fb_id); + munmap(page->mmap, page->mmap_size); + + destroy_dumb.handle = page->drm_dumb_handle; + ioctl(fb->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); // XXX: errors? + + free(page); +} + + static void drm_fb_shutdown(til_fb_t *fb, void *context) { drm_fb_t *c = context; + drm_fb_page_t *p; assert(c); + while ((p = c->spare_pages)) { + c->spare_pages = p->next_spare; + + _drm_fb_page_free(c, p); + } + close(c->drm_fd); drmModeFreeConnector(c->connector); drmModeFreeCrtc(c->crtc); @@ -459,45 +481,53 @@ static void * drm_fb_page_alloc(til_fb_t *fb, void *context, til_fb_fragment_t * struct drm_mode_map_dumb map_dumb = {}; uint32_t *map, fb_id; drm_fb_t *c = context; - drm_fb_page_t *p; - - p = calloc(1, sizeof(drm_fb_page_t)); - if (!p) - return NULL; - - create_dumb.width = c->mode->hdisplay; - create_dumb.height = c->mode->vdisplay; - - pexit_if(ioctl(c->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb) < 0, - "unable to create dumb buffer"); + drm_fb_page_t *p = NULL; - map_dumb.handle = create_dumb.handle; - pexit_if(ioctl(c->drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb) < 0, - "unable to prepare dumb buffer for mmap"); - pexit_if(!(map = mmap(NULL, create_dumb.size, PROT_READ|PROT_WRITE, MAP_SHARED, c->drm_fd, map_dumb.offset)), - "unable to mmap dumb buffer"); - pexit_if(drmModeAddFB(c->drm_fd, c->mode->hdisplay, c->mode->vdisplay, 24, 32, create_dumb.pitch, create_dumb.handle, &fb_id) < 0, - "unable to add dumb buffer"); - - /* prevent unaligned pitches, we're just simplifying everything in rototiller that wants - * to do word-at-a-time operations without concern for arches that get angry when that happens - * on unaligned addresses. - */ - assert(!(create_dumb.pitch & 0x3)); + if (c->spare_pages) { + p = c->spare_pages; + c->spare_pages = p->next_spare; + } - p->mmap = map; - p->mmap_size = create_dumb.size; - p->drm_dumb_handle = map_dumb.handle; - p->drm_fb_id = fb_id; + if (!p) { + p = calloc(1, sizeof(drm_fb_page_t)); + if (!p) + return NULL; + + create_dumb.width = c->mode->hdisplay; + create_dumb.height = c->mode->vdisplay; + + pexit_if(ioctl(c->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb) < 0, + "unable to create dumb buffer"); + + map_dumb.handle = create_dumb.handle; + pexit_if(ioctl(c->drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb) < 0, + "unable to prepare dumb buffer for mmap"); + pexit_if(!(map = mmap(NULL, create_dumb.size, PROT_READ|PROT_WRITE, MAP_SHARED, c->drm_fd, map_dumb.offset)), + "unable to mmap dumb buffer"); + pexit_if(drmModeAddFB(c->drm_fd, c->mode->hdisplay, c->mode->vdisplay, 24, 32, create_dumb.pitch, create_dumb.handle, &fb_id) < 0, + "unable to add dumb buffer"); + + /* prevent unaligned pitches, we're just simplifying everything in rototiller that wants + * to do word-at-a-time operations without concern for arches that get angry when that happens + * on unaligned addresses. + */ + assert(!(create_dumb.pitch & 0x3)); + + p->mmap = map; + p->mmap_size = create_dumb.size; + p->pitch = create_dumb.pitch >> 2; + p->drm_dumb_handle = map_dumb.handle; + p->drm_fb_id = fb_id; + } *res_fragment = (til_fb_fragment_t){ - .buf = map, + .buf = p->mmap, .width = c->mode->hdisplay, .frame_width = c->mode->hdisplay, .height = c->mode->vdisplay, .frame_height = c->mode->vdisplay, - .pitch = create_dumb.pitch >> 2, - .stride = (create_dumb.pitch >> 2) - c->mode->hdisplay, + .pitch = p->pitch, + .stride = p->pitch - c->mode->hdisplay, }; return p; @@ -506,17 +536,11 @@ static void * drm_fb_page_alloc(til_fb_t *fb, void *context, til_fb_fragment_t * static int drm_fb_page_free(til_fb_t *fb, void *context, void *page) { - struct drm_mode_destroy_dumb destroy_dumb = {}; - drm_fb_t *c = context; - drm_fb_page_t *p = page; - - drmModeRmFB(c->drm_fd, p->drm_fb_id); - munmap(p->mmap, p->mmap_size); - - destroy_dumb.handle = p->drm_dumb_handle; - ioctl(c->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); // XXX: errors? + drm_fb_t *c = context; + drm_fb_page_t *p = page; - free(p); + p->next_spare = c->spare_pages; + c->spare_pages = p; return 0; } -- cgit v1.2.3