summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amdgpu_kms.c80
-rw-r--r--src/drmmode_display.c80
-rw-r--r--src/drmmode_display.h3
3 files changed, 108 insertions, 55 deletions
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 7ec86fb..88b0be0 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -320,8 +320,6 @@ amdgpu_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents)
return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
}
-#ifdef AMDGPU_PIXMAP_SHARING
-
static RegionPtr
transform_region(RegionPtr region, struct pict_f_transform *transform,
int w, int h)
@@ -360,6 +358,62 @@ transform_region(RegionPtr region, struct pict_f_transform *transform,
return transformed;
}
+static void
+amdgpu_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;
+ RegionRec remaining;
+ RegionPtr sync_region = NULL;
+ BoxRec extents;
+ GCPtr gc;
+
+ if (RegionNil(last_region))
+ return;
+
+ RegionNull(&remaining);
+ RegionSubtract(&remaining, last_region, new_region);
+ if (RegionNil(&remaining))
+ goto uninit;
+
+ extents = *RegionExtents(&remaining);
+ if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
+ 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);
+ }
+
+ 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);
+ }
+
+ uninit:
+ if (sync_region)
+ RegionDestroy(sync_region);
+ RegionUninit(&remaining);
+}
+
+#ifdef AMDGPU_PIXMAP_SHARING
+
static RegionPtr
dirty_region(PixmapDirtyUpdatePtr dirty)
{
@@ -579,10 +633,11 @@ static Bool
amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
{
drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
- DamagePtr pDamage;
- RegionPtr pRegion;
+ RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
+ ScrnInfoPtr scrn = xf86_crtc->scrn;
+ ScreenPtr pScreen = scrn->pScreen;
+ AMDGPUInfoPtr info = AMDGPUPTR(scrn);
DrawablePtr pDraw;
- ScreenPtr pScreen;
BoxRec extents;
if (!xf86_crtc->enabled ||
@@ -590,21 +645,20 @@ amdgpu_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 (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
return FALSE;
+ if (info->tear_free) {
+ amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
+ RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
+ }
+ RegionEmpty(pRegion);
+
#if XF86_CRTC_VERSION >= 4
if (xf86_crtc->driverIsPerformingTransform) {
SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
@@ -708,7 +762,7 @@ amdgpu_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;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index a8ee5f0..1e4622d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -462,10 +462,20 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
amdgpu_bo_unref(&scanout->bo);
scanout->bo = 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 (scanout->damage) {
- DamageDestroy(scanout->damage);
- scanout->damage = NULL;
+ if (drmmode_crtc->scanout_damage) {
+ DamageDestroy(drmmode_crtc->scanout_damage);
+ drmmode_crtc->scanout_damage = NULL;
+ RegionUninit(&drmmode_crtc->scanout_last_region);
}
}
@@ -475,15 +485,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 *
@@ -726,33 +729,31 @@ 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(amdgpu_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 = 0;
- pBox->y1 = 0;
- pBox->x2 = max(pBox->x2, pScrn->virtualX);
- pBox->y2 = max(pBox->y2, pScrn->virtualY);
- }
}
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(amdgpu_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 = 0;
+ pBox->y1 = 0;
+ pBox->x2 = max(pBox->x2, pScrn->virtualX);
+ pBox->y2 = max(pBox->y2, pScrn->virtualY);
+
drmmode_crtc->scanout_id = 0;
fb_id = drmmode_crtc->scanout[0].fb_id;
x = y = 0;
@@ -840,10 +841,8 @@ done:
} else {
crtc->active = TRUE;
- if (fb_id != drmmode_crtc->scanout[0].fb_id) {
- drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
- drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
- }
+ if (fb_id != drmmode_crtc->scanout[0].fb_id)
+ drmmode_crtc_scanout_free(drmmode_crtc);
}
return ret;
@@ -1068,8 +1067,7 @@ static Bool 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 e739382..6c5542c 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -73,7 +73,6 @@ typedef struct {
struct drmmode_scanout {
struct amdgpu_buffer *bo;
PixmapPtr pixmap;
- DamagePtr damage;
unsigned fb_id;
int width, height;
};
@@ -85,6 +84,8 @@ typedef struct {
struct amdgpu_buffer *cursor_buffer;
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;