diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2017-04-29 17:05:58 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2017-05-11 18:51:38 +0900 |
commit | 55e513b978b2afc52b7cafc5bfcb0d1dc78d75f6 (patch) | |
tree | 127def07b6c217dc6990168652861356501d4882 /src/drmmode_display.h | |
parent | 944391b0052466b71bf9919b56139dc197a7e072 (diff) |
Use reference counting for tracking KMS framebuffer lifetimes
References are held by the pixmaps corresponding to the FBs (so
the same KMS FB can be reused as long as the pixmap exists) and by the
CRTCs scanning out from them (so a KMS FB is only destroyed once it's
not being scanned out anymore, preventing intermittent black screens and
worse issues due to a CRTC turning off when it should be on).
v2:
* Only increase reference count in drmmode_fb_reference if it was sane
before
* Make drmmode_fb_reference's indentation match the rest of
drmmode_display.h
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src/drmmode_display.h')
-rw-r--r-- | src/drmmode_display.h | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 35d64179..14d1cb03 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -41,7 +41,6 @@ typedef struct { int fd; - unsigned fb_id; drmModeFBPtr mode_fb; int cpp; struct radeon_bo_manager *bufmgr; @@ -60,7 +59,6 @@ typedef struct { } drmmode_rec, *drmmode_ptr; typedef struct { - unsigned old_fb_id; int flip_count; void *event_data; unsigned int fe_frame; @@ -70,10 +68,14 @@ typedef struct { radeon_drm_abort_proc abort; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; +struct drmmode_fb { + int refcnt; + uint32_t handle; +}; + struct drmmode_scanout { struct radeon_bo *bo; PixmapPtr pixmap; - unsigned fb_id; int width, height; }; @@ -102,8 +104,10 @@ typedef struct { * modeset) */ Bool need_modeset; - /* A flip is pending for this CRTC */ - Bool flip_pending; + /* A flip to this FB is pending for this CRTC */ + struct drmmode_fb *flip_pending; + /* The FB currently being scanned out by this CRTC, if any */ + struct drmmode_fb *fb; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -135,6 +139,31 @@ enum drmmode_flip_sync { }; +static inline void +drmmode_fb_reference(int drm_fd, struct drmmode_fb **old, struct drmmode_fb *new) +{ + if (new) { + if (new->refcnt <= 0) + ErrorF("New FB's refcnt was %d in %s\n", new->refcnt, __func__); + else + new->refcnt++; + } + + if (*old) { + if ((*old)->refcnt <= 0) { + ErrorF("Old FB's refcnt was %d in %s\n", (*old)->refcnt, __func__); + } else { + if (--(*old)->refcnt == 0) { + drmModeRmFB(drm_fd, (*old)->handle); + free(*old); + } + } + } + + *old = new; +} + + extern int drmmode_page_flip_target_absolute(RADEONEntPtr pRADEONEnt, drmmode_crtc_private_ptr drmmode_crtc, int fb_id, uint32_t flags, |