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;  | 
