summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c61
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;
}