mirror of
https://github.com/X11Libre/xf86-video-amdgpu.git
synced 2026-04-14 11:04:42 +00:00
Synchronize scanout pixmaps for TearFree
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. (Ported from radeon commit eda1f3df6aaed683036369fe8820da4dac3c2ae2) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
committed by
Michel Dänzer
parent
4927b84ec8
commit
d6feed2cd7
@@ -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;
|
||||
|
||||
|
||||
@@ -462,10 +462,20 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
|
||||
amdgpu_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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user