- U_01-* ... U_20-* : Include patches that haven't made it into the 7.7.1 release. This means almost all commits between xf86-video-ati-7.7.0 and 12d30eeb9711bd2b1609d6bbb74c4a1760596f72. Fixes (bsc#990066). OBS-URL: https://build.opensuse.org/request/show/438260 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xf86-video-ati?expand=0&rev=51
328 lines
10 KiB
Diff
328 lines
10 KiB
Diff
From: Michel Dänzer <michel.daenzer@amd.com>
|
|
Date: Thu Sep 1 12:54:13 2016 +0900
|
|
Subject: [PATCH 19/20]Synchronize scanout pixmaps for TearFree
|
|
Patch-mainline: Upstream
|
|
Git-repo: git://anongit.freedesktop.org/xorg/driver/xf86-video-ati
|
|
Git-commit: eda1f3df6aaed683036369fe8820da4dac3c2ae2
|
|
References: bsc#990066
|
|
Signed-off-by: Max Staudt <mstaudt@suse.de>
|
|
|
|
Copy the damaged areas which are still valid in the other scanout pixmap
|
|
from there, then only copy the remaining damaged area from the screen
|
|
pixmap.
|
|
|
|
This is slightly more efficient (only needs one Damage record instead of
|
|
two, and only needs to copy each screen update across PCIe once with
|
|
ShadowPrimary and a discrete GPU), and will be significantly more
|
|
efficient for PRIME with the following change.
|
|
|
|
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
|
|
---
|
|
src/drmmode_display.c | 95 +++++++++++++++++++++++++--------------------------
|
|
src/drmmode_display.h | 3 +-
|
|
src/radeon_kms.c | 92 ++++++++++++++++++++++++++++++++++++++++---------
|
|
3 files changed, 124 insertions(+), 66 deletions(-)
|
|
|
|
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
|
|
index 1fcd7c3..44a4032 100644
|
|
--- a/src/drmmode_display.c
|
|
+++ b/src/drmmode_display.c
|
|
@@ -519,10 +519,20 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
|
|
radeon_bo_unref(scanout->bo);
|
|
scanout->bo = NULL;
|
|
}
|
|
+}
|
|
|
|
- if (scanout->damage) {
|
|
- DamageDestroy(scanout->damage);
|
|
- scanout->damage = NULL;
|
|
+static void
|
|
+drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
|
|
+{
|
|
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
|
|
+ &drmmode_crtc->scanout[0]);
|
|
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
|
|
+ &drmmode_crtc->scanout[1]);
|
|
+
|
|
+ if (drmmode_crtc->scanout_damage) {
|
|
+ DamageDestroy(drmmode_crtc->scanout_damage);
|
|
+ drmmode_crtc->scanout_damage = NULL;
|
|
+ RegionUninit(&drmmode_crtc->scanout_last_region);
|
|
}
|
|
}
|
|
|
|
@@ -532,15 +542,8 @@ drmmode_scanout_free(ScrnInfoPtr scrn)
|
|
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
|
|
int c;
|
|
|
|
- for (c = 0; c < xf86_config->num_crtc; c++) {
|
|
- drmmode_crtc_private_ptr drmmode_crtc =
|
|
- xf86_config->crtc[c]->driver_private;
|
|
-
|
|
- drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
|
|
- &drmmode_crtc->scanout[0]);
|
|
- drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
|
|
- &drmmode_crtc->scanout[1]);
|
|
- }
|
|
+ for (c = 0; c < xf86_config->num_crtc; c++)
|
|
+ drmmode_crtc_scanout_free(xf86_config->crtc[c]->driver_private);
|
|
}
|
|
|
|
static void *
|
|
@@ -793,8 +796,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
|
fb_id = drmmode_crtc->rotate.fb_id;
|
|
x = y = 0;
|
|
|
|
- drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
|
|
- drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
|
|
+ drmmode_crtc_scanout_free(drmmode_crtc);
|
|
} else if (
|
|
#ifdef RADEON_PIXMAP_SHARING
|
|
!pScreen->isGPU &&
|
|
@@ -809,42 +811,40 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
|
|
&drmmode_crtc->scanout[i],
|
|
mode->HDisplay,
|
|
mode->VDisplay);
|
|
-
|
|
- if (drmmode_crtc->scanout[i].pixmap) {
|
|
- RegionPtr pRegion;
|
|
- BoxPtr pBox;
|
|
-
|
|
- if (!drmmode_crtc->scanout[i].damage) {
|
|
- drmmode_crtc->scanout[i].damage =
|
|
- DamageCreate(radeon_screen_damage_report,
|
|
- NULL, DamageReportRawRegion,
|
|
- TRUE, pScreen, NULL);
|
|
- DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
|
|
- drmmode_crtc->scanout[i].damage);
|
|
- }
|
|
-
|
|
- pRegion = DamageRegion(drmmode_crtc->scanout[i].damage);
|
|
- RegionUninit(pRegion);
|
|
- pRegion->data = NULL;
|
|
- pBox = RegionExtents(pRegion);
|
|
- pBox->x1 = min(pBox->x1, x);
|
|
- pBox->y1 = min(pBox->y1, y);
|
|
-
|
|
- switch (crtc->rotation & 0xf) {
|
|
- case RR_Rotate_90:
|
|
- case RR_Rotate_270:
|
|
- pBox->x2 = max(pBox->x2, x + mode->VDisplay);
|
|
- pBox->y2 = max(pBox->y2, y + mode->HDisplay);
|
|
- break;
|
|
- default:
|
|
- pBox->x2 = max(pBox->x2, x + mode->HDisplay);
|
|
- pBox->y2 = max(pBox->y2, y + mode->VDisplay);
|
|
- }
|
|
- }
|
|
}
|
|
|
|
if (drmmode_crtc->scanout[0].pixmap &&
|
|
(!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
|
|
+ RegionPtr pRegion;
|
|
+ BoxPtr pBox;
|
|
+
|
|
+ if (!drmmode_crtc->scanout_damage) {
|
|
+ drmmode_crtc->scanout_damage =
|
|
+ DamageCreate(radeon_screen_damage_report,
|
|
+ NULL, DamageReportRawRegion,
|
|
+ TRUE, pScreen, NULL);
|
|
+ DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
|
|
+ drmmode_crtc->scanout_damage);
|
|
+ }
|
|
+
|
|
+ pRegion = DamageRegion(drmmode_crtc->scanout_damage);
|
|
+ RegionUninit(pRegion);
|
|
+ pRegion->data = NULL;
|
|
+ pBox = RegionExtents(pRegion);
|
|
+ pBox->x1 = min(pBox->x1, x);
|
|
+ pBox->y1 = min(pBox->y1, y);
|
|
+
|
|
+ switch (crtc->rotation & 0xf) {
|
|
+ case RR_Rotate_90:
|
|
+ case RR_Rotate_270:
|
|
+ pBox->x2 = max(pBox->x2, x + mode->VDisplay);
|
|
+ pBox->y2 = max(pBox->y2, y + mode->HDisplay);
|
|
+ break;
|
|
+ default:
|
|
+ pBox->x2 = max(pBox->x2, x + mode->HDisplay);
|
|
+ pBox->y2 = max(pBox->y2, y + mode->VDisplay);
|
|
+ }
|
|
+
|
|
drmmode_crtc->scanout_id = 0;
|
|
fb_id = drmmode_crtc->scanout[0].fb_id;
|
|
x = y = 0;
|
|
@@ -1121,8 +1121,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
|
|
if (crtc->randr_crtc->scanout_pixmap)
|
|
PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap,
|
|
drmmode_crtc->scanout[0].pixmap);
|
|
- drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
|
|
- &drmmode_crtc->scanout[0]);
|
|
+ drmmode_crtc_scanout_free(drmmode_crtc);
|
|
return TRUE;
|
|
}
|
|
|
|
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
|
|
index 53c7926..5df9773 100644
|
|
--- a/src/drmmode_display.h
|
|
+++ b/src/drmmode_display.h
|
|
@@ -73,7 +73,6 @@ typedef struct {
|
|
struct drmmode_scanout {
|
|
struct radeon_bo *bo;
|
|
PixmapPtr pixmap;
|
|
- DamagePtr damage;
|
|
unsigned fb_id;
|
|
int width, height;
|
|
};
|
|
@@ -85,6 +84,8 @@ typedef struct {
|
|
struct radeon_bo *cursor_bo;
|
|
struct drmmode_scanout rotate;
|
|
struct drmmode_scanout scanout[2];
|
|
+ DamagePtr scanout_damage;
|
|
+ RegionRec scanout_last_region;
|
|
unsigned scanout_id;
|
|
Bool scanout_update_pending;
|
|
int dpms_mode;
|
|
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
|
|
index 568c49e..bcaa024 100644
|
|
--- a/src/radeon_kms.c
|
|
+++ b/src/radeon_kms.c
|
|
@@ -402,8 +402,6 @@ radeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents, int w,
|
|
return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
|
|
}
|
|
|
|
-#ifdef RADEON_PIXMAP_SHARING
|
|
-
|
|
static RegionPtr
|
|
transform_region(RegionPtr region, struct pict_f_transform *transform,
|
|
int w, int h)
|
|
@@ -442,6 +440,70 @@ transform_region(RegionPtr region, struct pict_f_transform *transform,
|
|
return transformed;
|
|
}
|
|
|
|
+static void
|
|
+radeon_sync_scanout_pixmaps(xf86CrtcPtr xf86_crtc, RegionPtr new_region,
|
|
+ int scanout_id)
|
|
+{
|
|
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
|
|
+ DrawablePtr dst = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
|
|
+ DrawablePtr src = &drmmode_crtc->scanout[scanout_id ^ 1].pixmap->drawable;
|
|
+ RegionPtr last_region = &drmmode_crtc->scanout_last_region;
|
|
+ ScrnInfoPtr scrn = xf86_crtc->scrn;
|
|
+ ScreenPtr pScreen = scrn->pScreen;
|
|
+ RADEONInfoPtr info = RADEONPTR(scrn);
|
|
+ RegionRec remaining;
|
|
+ RegionPtr sync_region = NULL;
|
|
+ BoxRec extents;
|
|
+ Bool force;
|
|
+ GCPtr gc;
|
|
+
|
|
+ if (RegionNil(last_region))
|
|
+ return;
|
|
+
|
|
+ RegionNull(&remaining);
|
|
+ RegionSubtract(&remaining, last_region, new_region);
|
|
+ if (RegionNil(&remaining))
|
|
+ goto uninit;
|
|
+
|
|
+ extents = *RegionExtents(&remaining);
|
|
+ if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, dst->width,
|
|
+ dst->height))
|
|
+ goto uninit;
|
|
+
|
|
+#if XF86_CRTC_VERSION >= 4
|
|
+ if (xf86_crtc->driverIsPerformingTransform) {
|
|
+ sync_region = transform_region(&remaining,
|
|
+ &xf86_crtc->f_framebuffer_to_crtc,
|
|
+ dst->width, dst->height);
|
|
+ } else
|
|
+#endif /* XF86_CRTC_VERSION >= 4 */
|
|
+ {
|
|
+ sync_region = RegionDuplicate(&remaining);
|
|
+ RegionTranslate(sync_region, -xf86_crtc->x, -xf86_crtc->y);
|
|
+ }
|
|
+
|
|
+ force = info->accel_state->force;
|
|
+ info->accel_state->force = TRUE;
|
|
+
|
|
+ gc = GetScratchGC(dst->depth, pScreen);
|
|
+ if (gc) {
|
|
+ ValidateGC(dst, gc);
|
|
+ gc->funcs->ChangeClip(gc, CT_REGION, sync_region, 0);
|
|
+ sync_region = NULL;
|
|
+ gc->ops->CopyArea(src, dst, gc, 0, 0, dst->width, dst->height, 0, 0);
|
|
+ FreeScratchGC(gc);
|
|
+ }
|
|
+
|
|
+ info->accel_state->force = force;
|
|
+
|
|
+ uninit:
|
|
+ if (sync_region)
|
|
+ RegionDestroy(sync_region);
|
|
+ RegionUninit(&remaining);
|
|
+}
|
|
+
|
|
+#ifdef RADEON_PIXMAP_SHARING
|
|
+
|
|
static RegionPtr
|
|
dirty_region(PixmapDirtyUpdatePtr dirty)
|
|
{
|
|
@@ -660,13 +722,12 @@ static Bool
|
|
radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
|
|
{
|
|
drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
|
|
- ScrnInfoPtr scrn;
|
|
- DamagePtr pDamage;
|
|
- RegionPtr pRegion;
|
|
+ RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
|
|
+ ScrnInfoPtr scrn = xf86_crtc->scrn;
|
|
+ ScreenPtr pScreen = scrn->pScreen;
|
|
+ RADEONInfoPtr info = RADEONPTR(scrn);
|
|
DrawablePtr pDraw;
|
|
- ScreenPtr pScreen;
|
|
BoxRec extents;
|
|
- RADEONInfoPtr info;
|
|
Bool force;
|
|
|
|
if (!xf86_crtc->enabled ||
|
|
@@ -674,24 +735,21 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
|
|
!drmmode_crtc->scanout[scanout_id].pixmap)
|
|
return FALSE;
|
|
|
|
- pDamage = drmmode_crtc->scanout[scanout_id].damage;
|
|
- if (!pDamage)
|
|
- return FALSE;
|
|
-
|
|
- pRegion = DamageRegion(pDamage);
|
|
if (!RegionNotEmpty(pRegion))
|
|
return FALSE;
|
|
|
|
pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
|
|
- pScreen = pDraw->pScreen;
|
|
extents = *RegionExtents(pRegion);
|
|
- RegionEmpty(pRegion);
|
|
if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width,
|
|
pDraw->height))
|
|
return FALSE;
|
|
|
|
- scrn = xf86_crtc->scrn;
|
|
- info = RADEONPTR(scrn);
|
|
+ if (info->tear_free) {
|
|
+ radeon_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
|
|
+ RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
|
|
+ }
|
|
+ RegionEmpty(pRegion);
|
|
+
|
|
force = info->accel_state->force;
|
|
info->accel_state->force = TRUE;
|
|
|
|
@@ -807,7 +865,7 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
|
|
drmmode_crtc->pending_dpms_mode != DPMSModeOn)
|
|
return;
|
|
|
|
- pDamage = drmmode_crtc->scanout[0].damage;
|
|
+ pDamage = drmmode_crtc->scanout_damage;
|
|
if (!pDamage)
|
|
return;
|
|
|