summaryrefslogtreecommitdiff
path: root/src/radeon.h
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-04-29 17:05:58 +0900
committerMichel Dänzer <michel@daenzer.net>2017-05-11 18:51:38 +0900
commit55e513b978b2afc52b7cafc5bfcb0d1dc78d75f6 (patch)
tree127def07b6c217dc6990168652861356501d4882 /src/radeon.h
parent944391b0052466b71bf9919b56139dc197a7e072 (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/radeon.h')
-rw-r--r--src/radeon.h73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/radeon.h b/src/radeon.h
index 2cb188e1..febe580b 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -288,6 +288,7 @@ struct radeon_pixmap {
uint_fast32_t gpu_write;
struct radeon_bo *bo;
+ struct drmmode_fb *fb;
uint32_t tiling_flags;
@@ -313,6 +314,7 @@ static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pix
struct radeon_exa_pixmap_priv {
struct radeon_bo *bo;
+ struct drmmode_fb *fb;
uint32_t tiling_flags;
struct radeon_surface surface;
Bool bo_mapped;
@@ -609,6 +611,9 @@ extern void RADEONCopySwap(uint8_t *dst, uint8_t *src, unsigned int size, int s
extern void RADEONInit3DEngine(ScrnInfoPtr pScrn);
extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn);
+/* radeon_bo_helper.c */
+extern Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle);
+
/* radeon_commonfuncs.c */
extern void RADEONWaitForVLine(ScrnInfoPtr pScrn, PixmapPtr pPix,
xf86CrtcPtr crtc, int start, int stop);
@@ -706,6 +711,8 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
radeon_bo_unref(priv->bo);
}
+ drmmode_fb_reference(info->drmmode.fd, &priv->fb, NULL);
+
if (!bo) {
free(priv);
priv = NULL;
@@ -790,6 +797,72 @@ static inline Bool radeon_get_pixmap_shared(PixmapPtr pPix)
return FALSE;
}
+static inline struct drmmode_fb*
+radeon_fb_create(int drm_fd, uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t handle)
+{
+ struct drmmode_fb *fb = malloc(sizeof(*fb));
+
+ if (!fb)
+ return NULL;
+
+ fb->refcnt = 1;
+ if (drmModeAddFB(drm_fd, width, height, depth, bpp, pitch, handle,
+ &fb->handle) == 0)
+ return fb;
+
+ free(fb);
+ return NULL;
+}
+
+static inline struct drmmode_fb*
+radeon_pixmap_create_fb(int drm_fd, PixmapPtr pix)
+{
+ uint32_t handle;
+
+ if (!radeon_get_pixmap_handle(pix, &handle))
+ return NULL;
+
+ return radeon_fb_create(drm_fd, pix->drawable.width, pix->drawable.height,
+ pix->drawable.depth, pix->drawable.bitsPerPixel,
+ pix->devKind, handle);
+}
+
+static inline struct drmmode_fb*
+radeon_pixmap_get_fb(PixmapPtr pix)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pix->drawable.pScreen));
+
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pix);
+
+ if (!priv)
+ return NULL;
+
+ if (!priv->fb)
+ priv->fb = radeon_pixmap_create_fb(info->drmmode.fd, pix);
+
+ return priv->fb;
+ } else
+#endif
+ if (info->accelOn)
+ {
+ struct radeon_exa_pixmap_priv *driver_priv =
+ exaGetPixmapDriverPrivate(pix);
+
+ if (!driver_priv)
+ return NULL;
+
+ if (!driver_priv->fb)
+ driver_priv->fb = radeon_pixmap_create_fb(info->drmmode.fd, pix);
+
+ return driver_priv->fb;
+ }
+
+ return NULL;
+}
+
#define CP_PACKET0(reg, n) \
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CP_PACKET1(reg0, reg1) \