diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2023-11-18 09:33:37 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2023-11-18 09:33:37 -0800 |
commit | 1d11a76d8361b52e0f7a489afe99ff08583a8333 (patch) | |
tree | 9dd86f214c1a7c5ed816f9c7691317cf48662971 | |
parent | f15e1ada07a08a6dd13dcf648e815f2c9620ce6e (diff) |
drm_fb: use shadow buffers when device prefers it
I noticed the sdl_fb backend seemed to often have significantly
better FPS in fullscreen use vs. drm_fb fullscreen. Looking at
the libdrm api I saw this PREFER_SHADOW capability and noticed my
laptop's gpu driver sets it... With this change, despite the
additional memcpy(), the drm fullscreen FPS seems significantly
better.
A subsequent commit will make this an overridable runtime setting
-rw-r--r-- | src/drm_fb.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/src/drm_fb.c b/src/drm_fb.c index a3864d3..5d7f259 100644 --- a/src/drm_fb.c +++ b/src/drm_fb.c @@ -21,6 +21,7 @@ typedef struct drm_fb_page_t drm_fb_page_t; struct drm_fb_page_t { drm_fb_page_t *next_spare; uint32_t *mmap; + uint32_t *shadow; size_t mmap_size, pitch; uint32_t drm_dumb_handle; uint32_t drm_fb_id; @@ -32,6 +33,7 @@ typedef struct drm_fb_t { drmModeConnector *connector; drmModeModeInfo *mode; drm_fb_page_t *spare_pages; + unsigned use_shadow:1; } drm_fb_t; typedef struct drm_fb_setup_t { @@ -381,6 +383,13 @@ static int drm_fb_init(const char *title, const til_setup_t *setup, void **res_c goto _err_enc; } + { + uint64_t use_shadow; + + if (!drmGetCap(c->drm_fd, DRM_CAP_DUMB_PREFER_SHADOW, &use_shadow) && use_shadow) + c->use_shadow = 1; + } + drmModeFreeEncoder(enc); *res_context = c; @@ -410,6 +419,7 @@ static void _drm_fb_page_free(drm_fb_t *fb, drm_fb_page_t *page) destroy_dumb.handle = page->drm_dumb_handle; ioctl(fb->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); // XXX: errors? + free(page->shadow); free(page); } @@ -487,6 +497,11 @@ static void * drm_fb_page_alloc(til_fb_t *fb, void *context, til_fb_fragment_t * */ assert(!(create_dumb.pitch & 0x3)); + if (c->use_shadow) { + pexit_if(!(p->shadow = malloc(create_dumb.size)), + "unable to allocate page shadow buffer"); + } + p->mmap = map; p->mmap_size = create_dumb.size; p->pitch = create_dumb.pitch >> 2; @@ -495,7 +510,7 @@ static void * drm_fb_page_alloc(til_fb_t *fb, void *context, til_fb_fragment_t * } *res_fragment = (til_fb_fragment_t){ - .buf = p->mmap, + .buf = p->shadow ? : p->mmap, .width = c->mode->hdisplay, .frame_width = c->mode->hdisplay, .height = c->mode->vdisplay, @@ -530,6 +545,9 @@ static int drm_fb_page_flip(til_fb_t *fb, void *context, void *page) drm_fb_t *c = context; drm_fb_page_t *p = page; + if (p->shadow) + memcpy(p->mmap, p->shadow, p->mmap_size); + if (drmModePageFlip(c->drm_fd, c->crtc->crtc_id, p->drm_fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL) < 0) return -1; |