diff options
-rw-r--r-- | src/drmmode_display.c | 147 | ||||
-rw-r--r-- | src/drmmode_display.h | 39 | ||||
-rw-r--r-- | src/radeon.h | 73 | ||||
-rw-r--r-- | src/radeon_bo_helper.h | 3 | ||||
-rw-r--r-- | src/radeon_exa.c | 2 | ||||
-rw-r--r-- | src/radeon_kms.c | 64 | ||||
-rw-r--r-- | 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 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; |