summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drmmode_display.c147
-rw-r--r--src/drmmode_display.h39
-rw-r--r--src/radeon.h73
-rw-r--r--src/radeon_bo_helper.h3
-rw-r--r--src/radeon_exa.c2
-rw-r--r--src/radeon_kms.c64
-rw-r--r--src/radeon_present.c8
7 files changed, 226 insertions, 110 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index a101ac23..ec307262 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -375,6 +375,7 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
0, 0, 0, NULL, 0, NULL);
+ drmmode_fb_reference(drmmode->fd, &drmmode_crtc->fb, NULL);
} else if (drmmode_crtc->dpms_mode != DPMSModeOn)
crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
crtc->x, crtc->y);
@@ -447,8 +448,9 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
RADEONInfoPtr info = RADEONPTR(pScrn);
- PixmapPtr src, dst;
ScreenPtr pScreen = pScrn->pScreen;
+ PixmapPtr src, dst = pScreen->GetScreenPixmap(pScreen);
+ struct drmmode_fb *fb = radeon_pixmap_get_fb(dst);
int fbcon_id = 0;
Bool force;
GCPtr gc;
@@ -464,7 +466,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
if (!fbcon_id)
return;
- if (fbcon_id == drmmode->fb_id) {
+ if (fbcon_id == fb->handle) {
/* in some rare case there might be no fbcon and we might already
* be the one with the current fb to avoid a false deadlck in
* kernel ttm code just do nothing as anyway there is nothing
@@ -477,8 +479,6 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
if (!src)
return;
- dst = pScreen->GetScreenPixmap(pScreen);
-
gc = GetScratchGC(pScrn->depth, pScreen);
ValidateGC(&dst->drawable, gc);
@@ -505,8 +505,6 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
}
if (scanout->bo) {
- drmModeRmFB(drmmode->fd, scanout->fb_id);
- scanout->fb_id = 0;
radeon_bo_unmap(scanout->bo);
radeon_bo_unref(scanout->bo);
scanout->bo = NULL;
@@ -571,15 +569,9 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
scanout->bo = radeon_alloc_pixmap_bo(pScrn, width, height, pScrn->depth,
tiling, pScrn->bitsPerPixel,
&pitch, &surface, &tiling);
- if (scanout->bo == NULL)
- goto error;
-
- if (drmModeAddFB(drmmode->fd, width, height, pScrn->depth,
- pScrn->bitsPerPixel, pitch,
- scanout->bo->handle,
- &scanout->fb_id) != 0) {
- ErrorF("failed to add scanout fb\n");
- goto error;
+ if (!scanout->bo) {
+ ErrorF("failed to create CRTC scanout BO\n");
+ return NULL;
}
scanout->pixmap = drmmode_create_bo_pixmap(pScrn,
@@ -587,13 +579,17 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
pScrn->depth,
pScrn->bitsPerPixel,
pitch, scanout->bo, NULL);
- if (scanout->pixmap) {
+ if (!scanout->pixmap) {
+ ErrorF("failed to create CRTC scanout pixmap\n");
+ goto error;
+ }
+
+ if (radeon_pixmap_get_fb(scanout->pixmap)) {
scanout->width = width;
scanout->height = height;
} else {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Couldn't allocate scanout pixmap for CRTC\n");
-error:
+ ErrorF("failed to create CRTC scanout FB\n");
+error:
drmmode_crtc_scanout_destroy(drmmode, scanout);
}
@@ -706,8 +702,8 @@ drmmode_handle_transform(xf86CrtcPtr crtc)
static void
drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
- unsigned scanout_id, int *fb_id, int *x,
- int *y)
+ unsigned scanout_id, struct drmmode_fb **fb,
+ int *x, int *y)
{
ScrnInfoPtr scrn = crtc->scrn;
ScreenPtr screen = scrn->pScreen;
@@ -759,7 +755,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
}
}
- *fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
+ *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
*x = *y = 0;
drmmode_crtc->scanout_id = scanout_id;
}
@@ -768,7 +764,8 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
static void
drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
- unsigned scanout_id, int *fb_id, int *x, int *y)
+ unsigned scanout_id, struct drmmode_fb **fb, int *x,
+ int *y)
{
ScrnInfoPtr scrn = crtc->scrn;
ScreenPtr screen = scrn->pScreen;
@@ -804,7 +801,7 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
box->x2 = max(box->x2, scrn->virtualX);
box->y2 = max(box->y2, scrn->virtualY);
- *fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
+ *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
*x = *y = 0;
radeon_scanout_do_update(crtc, scanout_id);
@@ -841,7 +838,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
int output_count = 0;
Bool ret = FALSE;
int i;
- int fb_id;
+ struct drmmode_fb *fb = NULL;
drmModeModeInfo kmode;
/* The root window contents may be undefined before the WindowExposures
@@ -889,15 +886,14 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
- fb_id = drmmode->fb_id;
#ifdef RADEON_PIXMAP_SHARING
if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
- &fb_id, &x, &y);
+ &fb, &x, &y);
} else
#endif
- if (drmmode_crtc->rotate.fb_id) {
- fb_id = drmmode_crtc->rotate.fb_id;
+ if (drmmode_crtc->rotate.pixmap) {
+ fb = radeon_pixmap_get_fb(drmmode_crtc->rotate.pixmap);
x = y = 0;
} else if (!radeon_is_gpu_screen(pScreen) &&
@@ -907,22 +903,24 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
#endif
info->shadow_primary)) {
drmmode_crtc_scanout_update(crtc, mode, scanout_id,
- &fb_id, &x, &y);
+ &fb, &x, &y);
}
- if (fb_id == 0) {
- if (drmModeAddFB(drmmode->fd,
- pScrn->virtualX,
- pScrn->virtualY,
- pScrn->depth, pScrn->bitsPerPixel,
- pScrn->displayWidth * info->pixel_bytes,
- info->front_bo->handle,
- &drmmode->fb_id) < 0) {
- ErrorF("failed to add fb\n");
- goto done;
- }
-
- fb_id = drmmode->fb_id;
+ if (!fb)
+ fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root));
+ if (!fb) {
+ fb = radeon_fb_create(drmmode->fd, pScrn->virtualX,
+ pScrn->virtualY, pScrn->depth,
+ pScrn->bitsPerPixel,
+ pScrn->displayWidth * info->pixel_bytes,
+ info->front_bo->handle);
+ /* Prevent refcnt of ad-hoc FBs from reaching 2 */
+ drmmode_fb_reference(drmmode->fd, &drmmode_crtc->fb, NULL);
+ drmmode_crtc->fb = fb;
+ }
+ if (!fb) {
+ ErrorF("failed to add FB for modeset\n");
+ goto done;
}
/* Wait for any pending flip to finish */
@@ -932,13 +930,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (drmModeSetCrtc(drmmode->fd,
drmmode_crtc->mode_crtc->crtc_id,
- fb_id, x, y, output_ids,
+ fb->handle, x, y, output_ids,
output_count, &kmode) != 0) {
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
"failed to set mode: %s\n", strerror(errno));
goto done;
- } else
+ } else {
ret = TRUE;
+ drmmode_fb_reference(drmmode->fd, &drmmode_crtc->fb, fb);
+ }
if (pScreen)
xf86CrtcSetScreenSubpixelOrder(pScreen);
@@ -983,7 +983,9 @@ done:
} else {
crtc->active = TRUE;
- if (fb_id != drmmode_crtc->scanout[scanout_id].fb_id)
+ if (drmmode_crtc->scanout[scanout_id].pixmap &&
+ fb != radeon_pixmap_get_fb(drmmode_crtc->
+ scanout[scanout_id].pixmap))
drmmode_crtc_scanout_free(drmmode_crtc);
else if (!drmmode_crtc->tear_free) {
drmmode_crtc_scanout_destroy(drmmode,
@@ -2157,13 +2159,9 @@ static Bool
drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
- drmmode_crtc_private_ptr
- drmmode_crtc = xf86_config->crtc[0]->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
RADEONInfoPtr info = RADEONPTR(scrn);
struct radeon_bo *old_front = NULL;
ScreenPtr screen = xf86ScrnToScreen(scrn);
- uint32_t old_fb_id;
int i, pitch, old_width, old_height, old_pitch;
int aligned_height;
uint32_t screen_size;
@@ -2263,8 +2261,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
old_width = scrn->virtualX;
old_height = scrn->virtualY;
old_pitch = scrn->displayWidth;
- old_fb_id = drmmode->fb_id;
- drmmode->fb_id = 0;
old_front = info->front_bo;
scrn->virtualX = width;
@@ -2346,8 +2342,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
crtc->rotation, crtc->x, crtc->y);
}
- if (old_fb_id)
- drmModeRmFB(drmmode->fd, old_fb_id);
if (old_front)
radeon_bo_unref(old_front);
@@ -2361,7 +2355,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->virtualX = old_width;
scrn->virtualY = old_height;
scrn->displayWidth = old_pitch;
- drmmode->fb_id = old_fb_id;
return FALSE;
}
@@ -2375,7 +2368,7 @@ drmmode_clear_pending_flip(xf86CrtcPtr crtc)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_crtc->flip_pending = FALSE;
+ drmmode_crtc->flip_pending = NULL;
if (!crtc->enabled ||
(drmmode_crtc->pending_dpms_mode != DPMSModeOn &&
@@ -2419,7 +2412,7 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data)
static void
drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *event_data)
{
- RADEONInfoPtr info = RADEONPTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_flipdata_ptr flipdata = event_data;
/* Is this the event whose info shall be delivered to higher level? */
@@ -2439,12 +2432,11 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even
else
flipdata->handler(crtc, frame, usec, flipdata->event_data);
- /* Release framebuffer */
- drmModeRmFB(info->drmmode.fd, flipdata->old_fb_id);
-
free(flipdata);
}
+ drmmode_fb_reference(drmmode_crtc->drmmode->fd, &drmmode_crtc->fb,
+ drmmode_crtc->flip_pending);
drmmode_clear_pending_flip(crtc);
}
@@ -2701,6 +2693,8 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
drmModeSetCrtc(drmmode->fd,
drmmode_crtc->mode_crtc->crtc_id,
0, 0, 0, NULL, 0, NULL);
+ drmmode_fb_reference(drmmode->fd,
+ &drmmode_crtc->fb, NULL);
}
continue;
}
@@ -2960,18 +2954,11 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
xf86CrtcPtr crtc = NULL;
drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
int i;
uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0;
drmmode_flipdata_ptr flipdata;
uintptr_t drm_queue_seq = 0;
- uint32_t new_front_handle;
-
- if (!radeon_get_pixmap_handle(new_front, &new_front_handle)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "flip queue: failed to get new front handle\n");
- return FALSE;
- }
+ struct drmmode_fb *fb;
flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
if (!flipdata) {
@@ -2980,15 +2967,11 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
goto error;
}
- /*
- * Create a new handle for the back buffer
- */
- flipdata->old_fb_id = drmmode->fb_id;
- if (drmModeAddFB(drmmode->fd, new_front->drawable.width,
- new_front->drawable.height, scrn->depth,
- scrn->bitsPerPixel, new_front->devKind,
- new_front_handle, &drmmode->fb_id))
+ fb = radeon_pixmap_get_fb(new_front);
+ if (!fb) {
+ ErrorF("Failed to get FB for flip\n");
goto error;
+ }
/*
* Queue flips on all enabled CRTCs
@@ -3032,7 +3015,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
if (drmmode_crtc->hw_id == ref_crtc_hw_id) {
if (drmmode_page_flip_target_absolute(pRADEONEnt,
drmmode_crtc,
- drmmode->fb_id,
+ fb->handle,
flip_flags,
drm_queue_seq,
target_msc) != 0)
@@ -3040,13 +3023,13 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
} else {
if (drmmode_page_flip_target_relative(pRADEONEnt,
drmmode_crtc,
- drmmode->fb_id,
+ fb->handle,
flip_flags,
drm_queue_seq, 0) != 0)
goto flip_error;
}
- drmmode_crtc->flip_pending = TRUE;
+ drmmode_crtc->flip_pending = fb;
drm_queue_seq = 0;
}
@@ -3058,12 +3041,6 @@ flip_error:
strerror(errno));
error:
- if (flipdata && flipdata->flip_count <= 1 &&
- drmmode->fb_id != flipdata->old_fb_id) {
- drmModeRmFB(drmmode->fd, drmmode->fb_id);
- drmmode->fb_id = flipdata->old_fb_id;
- }
-
if (drm_queue_seq)
radeon_drm_abort_entry(drm_queue_seq);
else if (crtc)
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,
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) \
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
index f1aed551..77134250 100644
--- a/src/radeon_bo_helper.h
+++ b/src/radeon_bo_helper.h
@@ -28,9 +28,6 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
int usage_hint, int bitsPerPixel, int *new_pitch,
struct radeon_surface *new_surface, uint32_t *new_tiling);
-extern Bool
-radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle);
-
extern uint32_t
radeon_get_pixmap_tiling_flags(PixmapPtr pPix);
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 1e457a8b..d8dd7fdc 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -300,6 +300,7 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen));
struct radeon_exa_pixmap_priv *driver_priv = driverPriv;
if (!driverPriv)
@@ -307,6 +308,7 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
if (driver_priv->bo)
radeon_bo_unref(driver_priv->bo);
+ drmmode_fb_reference(info->drmmode.fd, &driver_priv->fb, NULL);
free(driverPriv);
}
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index b3427c46..2b410eb3 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -772,6 +772,17 @@ radeon_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
}
static void
+radeon_prime_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
+ void *event_data)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = event_data;
+
+ drmmode_fb_reference(drmmode_crtc->drmmode->fd, &drmmode_crtc->fb,
+ drmmode_crtc->flip_pending);
+ radeon_prime_scanout_flip_abort(crtc, event_data);
+}
+
+static void
radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
{
ScreenPtr screen = ent->slave_dst->drawable.pScreen;
@@ -798,7 +809,8 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
drm_queue_seq = radeon_drm_queue_alloc(crtc,
RADEON_DRM_QUEUE_CLIENT_DEFAULT,
RADEON_DRM_QUEUE_ID_DEFAULT,
- drmmode_crtc, NULL,
+ drmmode_crtc,
+ radeon_prime_scanout_flip_handler,
radeon_prime_scanout_flip_abort);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -806,8 +818,17 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
return;
}
+ drmmode_crtc->flip_pending =
+ radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+ if (!drmmode_crtc->flip_pending) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to get FB for PRIME flip.\n");
+ radeon_drm_abort_entry(drm_queue_seq);
+ return;
+ }
+
if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
- drmmode_crtc->scanout[scanout_id].fb_id,
+ drmmode_crtc->flip_pending->handle,
0, drm_queue_seq, 0) != 0) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
__func__, strerror(errno));
@@ -817,7 +838,6 @@ radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
drmmode_crtc->scanout_id = scanout_id;
drmmode_crtc->scanout_update_pending = TRUE;
- drmmode_crtc->flip_pending = TRUE;
}
static void
@@ -1053,10 +1073,14 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
static void
radeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
{
- drmmode_crtc_private_ptr drmmode_crtc = event_data;
+ radeon_prime_scanout_flip_abort(crtc, event_data);
+}
- drmmode_crtc->scanout_update_pending = FALSE;
- drmmode_clear_pending_flip(crtc);
+static void
+radeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec,
+ void *event_data)
+{
+ radeon_prime_scanout_flip_handler(crtc, msc, usec, event_data);
}
static void
@@ -1080,7 +1104,8 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc,
RADEON_DRM_QUEUE_CLIENT_DEFAULT,
RADEON_DRM_QUEUE_ID_DEFAULT,
- drmmode_crtc, NULL,
+ drmmode_crtc,
+ radeon_scanout_flip_handler,
radeon_scanout_flip_abort);
if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1088,8 +1113,17 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
return;
}
+ drmmode_crtc->flip_pending =
+ radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap);
+ if (!drmmode_crtc->flip_pending) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to get FB for scanout flip.\n");
+ radeon_drm_abort_entry(drm_queue_seq);
+ return;
+ }
+
if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc,
- drmmode_crtc->scanout[scanout_id].fb_id,
+ drmmode_crtc->flip_pending->handle,
0, drm_queue_seq, 0) != 0) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
__func__, strerror(errno));
@@ -1099,7 +1133,6 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
drmmode_crtc->scanout_id = scanout_id;
drmmode_crtc->scanout_update_pending = TRUE;
- drmmode_crtc->flip_pending = TRUE;
}
static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
@@ -1114,6 +1147,19 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ if (!pScrn->vtSema) {
+ radeon_cs_flush_indirect(pScrn);
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ drmmode_crtc_private_ptr drmmode_crtc =
+ xf86_config->crtc[c]->driver_private;
+
+ drmmode_fb_reference(info->drmmode.fd, &drmmode_crtc->fb, NULL);
+ }
+
+ return;
+ }
+
if (!radeon_is_gpu_screen(pScreen))
{
for (c = 0; c < xf86_config->num_crtc; c++) {
diff --git a/src/radeon_present.c b/src/radeon_present.c
index 90632d0e..635d1086 100644
--- a/src/radeon_present.c
+++ b/src/radeon_present.c
@@ -373,7 +373,6 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
enum drmmode_flip_sync flip_sync =
(radeon_present_screen_info.capabilities & PresentCapabilityAsync) ?
FLIP_ASYNC : FLIP_VSYNC;
- int old_fb_id;
int i;
radeon_cs_flush_indirect(scrn);
@@ -396,12 +395,6 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
return;
modeset:
- /* info->drmmode.fb_id still points to the FB for the last flipped BO.
- * Clear it, drmmode_set_mode_major will re-create it
- */
- old_fb_id = info->drmmode.fb_id;
- info->drmmode.fb_id = 0;
-
radeon_bo_wait(info->front_bo);
for (i = 0; i < config->num_crtc; i++) {
xf86CrtcPtr crtc = config->crtc[i];
@@ -417,7 +410,6 @@ modeset:
drmmode_crtc->need_modeset = TRUE;
}
- drmModeRmFB(info->drmmode.fd, old_fb_id);
present_event_notify(event_id, 0, 0);
info->drmmode.present_flipping = FALSE;