> -----Original Message----- > From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf > Of Michel Dänzer > Sent: Wednesday, May 10, 2017 5:06 AM > To: amd-gfx at lists.freedesktop.org > Subject: [PATCH xf86-video-ati 2/2] Use reference counting for tracking KMS > framebuffer lifetimes > > From: Michel Dänzer <michel.daenzer at amd.com> > > 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 at amd.com> # v1 > Signed-off-by: Michel Dänzer <michel.daenzer at amd.com> Series is: Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > --- > src/drmmode_display.c | 147 +++++++++++++++++++++----------------------- > ----- > src/drmmode_display.h | 39 +++++++++++-- > src/radeon.h | 73 ++++++++++++++++++++++++ > src/radeon_bo_helper.h | 3 - > src/radeon_exa.c | 2 + > src/radeon_kms.c | 64 ++++++++++++++++++--- > src/radeon_present.c | 8 --- > 7 files changed, 226 insertions(+), 110 deletions(-) > > diff --git a/src/drmmode_display.c b/src/drmmode_display.c > index a101ac233..ec3072621 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 35d64179d..14d1cb034 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 2cb188e1f..febe580b6 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 f1aed5516..771342502 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 1e457a8bb..d8dd7fdce 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 b3427c462..2b410eb3d 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 90632d0ec..635d10861 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; > -- > 2.11.0 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx