summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-11-18 09:33:37 -0800
committerVito Caputo <vcaputo@pengaru.com>2023-11-18 09:33:37 -0800
commit1d11a76d8361b52e0f7a489afe99ff08583a8333 (patch)
tree9dd86f214c1a7c5ed816f9c7691317cf48662971
parentf15e1ada07a08a6dd13dcf648e815f2c9620ce6e (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.c20
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;
© All Rights Reserved