diff options
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r-- | src/drmmode_display.c | 61 |
1 files changed, 54 insertions, 7 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 1ce58d1e..90588671 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -612,6 +612,14 @@ error: static void radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure) { + drmmode_crtc_private_ptr drmmode_crtc = closure; + + if (drmmode_crtc->ignore_damage) { + RegionEmpty(&damage->damage); + drmmode_crtc->ignore_damage = FALSE; + return; + } + /* Only keep track of the extents */ RegionUninit(&damage->damage); damage->damage.data = NULL; @@ -2429,7 +2437,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, flipdata->fb); - if (drmmode_crtc->flip_pending == flipdata->fb) { + if (drmmode_crtc->tear_free || + drmmode_crtc->flip_pending == flipdata->fb) { drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, NULL); } @@ -2998,13 +3007,16 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, flipdata->fe_crtc = ref_crtc; for (i = 0; i < config->num_crtc; i++) { + struct drmmode_fb *fb = flipdata->fb; + crtc = config->crtc[i]; + drmmode_crtc = crtc->driver_private; - if (!drmmode_crtc_can_flip(crtc)) + if (!drmmode_crtc_can_flip(crtc) || + (drmmode_crtc->tear_free && crtc != ref_crtc)) continue; flipdata->flip_count++; - drmmode_crtc = crtc->driver_private; drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, flipdata, @@ -3016,10 +3028,39 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto error; } + if (drmmode_crtc->tear_free) { + BoxRec extents = { .x1 = 0, .y1 = 0, + .x2 = new_front->drawable.width, + .y2 = new_front->drawable.height }; + int scanout_id = drmmode_crtc->scanout_id ^ 1; + + if (flip_sync == FLIP_ASYNC) { + if (!drmmode_wait_vblank(crtc, + DRM_VBLANK_RELATIVE | + DRM_VBLANK_EVENT, + 0, drm_queue_seq, + NULL, NULL)) + goto flip_error; + goto next; + } + + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + ErrorF("Failed to get FB for TearFree flip\n"); + goto error; + } + + radeon_scanout_do_update(crtc, scanout_id, + &new_front->drawable, &extents); + + drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, + drmmode_crtc->scanout_update_pending); + } + if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pRADEONEnt, drmmode_crtc, - flipdata->fb->handle, + fb->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -3027,14 +3068,20 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - flipdata->fb->handle, + fb->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - flipdata->fb); + if (drmmode_crtc->tear_free) { + drmmode_crtc->scanout_id ^= 1; + drmmode_crtc->ignore_damage = TRUE; + } + + next: + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->flip_pending, fb); drm_queue_seq = 0; } |