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.c162
1 files changed, 146 insertions, 16 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 303848f..40439dd 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -587,6 +587,34 @@ drmmode_can_use_hw_cursor(xf86CrtcPtr crtc)
return TRUE;
}
+static void
+drmmode_crtc_update_tear_free(xf86CrtcPtr crtc)
+{
+ AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ int i;
+
+ drmmode_crtc->tear_free = FALSE;
+
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+
+ if (output->crtc != crtc)
+ continue;
+
+ if (drmmode_output->tear_free == 1 ||
+ (drmmode_output->tear_free == 2 &&
+ (amdgpu_is_gpu_screen(crtc->scrn->pScreen) ||
+ info->shadow_primary ||
+ crtc->transformPresent || crtc->rotation != RR_Rotate_0))) {
+ drmmode_crtc->tear_free = TRUE;
+ return;
+ }
+ }
+}
+
#if XF86_CRTC_VERSION >= 4
#if XF86_CRTC_VERSION < 7
@@ -621,24 +649,86 @@ drmmode_handle_transform(xf86CrtcPtr crtc)
#endif
+#ifdef AMDGPU_PIXMAP_SHARING
+
+static void
+drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
+ unsigned scanout_id, int *fb_id, int *x,
+ int *y)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ ScreenPtr screen = scrn->pScreen;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (drmmode_crtc->tear_free &&
+ !drmmode_crtc->scanout[1].pixmap) {
+ RegionPtr region;
+ BoxPtr box;
+
+ drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
+ mode->HDisplay,
+ mode->VDisplay);
+ region = &drmmode_crtc->scanout_last_region;
+ RegionUninit(region);
+ region->data = NULL;
+ box = RegionExtents(region);
+ box->x1 = crtc->x;
+ box->y1 = crtc->y;
+ box->x2 = crtc->x + mode->HDisplay;
+ box->y2 = crtc->y + mode->VDisplay;
+ }
+
+ if (scanout_id != drmmode_crtc->scanout_id) {
+ PixmapDirtyUpdatePtr dirty = NULL;
+
+ xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list,
+ ent) {
+ if (dirty->src == crtc->randr_crtc->scanout_pixmap &&
+ dirty->slave_dst ==
+ drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) {
+ dirty->slave_dst =
+ drmmode_crtc->scanout[scanout_id].pixmap;
+ break;
+ }
+ }
+
+ if (!drmmode_crtc->tear_free) {
+ GCPtr gc = GetScratchGC(scrn->depth, screen);
+
+ ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc);
+ gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable,
+ &drmmode_crtc->scanout[0].pixmap->drawable,
+ gc, 0, 0, mode->HDisplay, mode->VDisplay,
+ 0, 0);
+ FreeScratchGC(gc);
+ amdgpu_glamor_finish(scrn);
+ }
+ }
+
+ *fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
+ *x = *y = 0;
+ drmmode_crtc->scanout_id = scanout_id;
+}
+
+#endif /* AMDGPU_PIXMAP_SHARING */
+
static void
drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
unsigned scanout_id, int *fb_id, int *x, int *y)
{
ScrnInfoPtr scrn = crtc->scrn;
ScreenPtr screen = scrn->pScreen;
- AMDGPUInfoPtr info = AMDGPUPTR(scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0],
mode->HDisplay, mode->VDisplay);
- if (info->tear_free) {
+ if (drmmode_crtc->tear_free) {
drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
mode->HDisplay, mode->VDisplay);
}
if (drmmode_crtc->scanout[0].pixmap &&
- (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
+ (!drmmode_crtc->tear_free || drmmode_crtc->scanout[1].pixmap)) {
RegionPtr region;
BoxPtr box;
@@ -678,7 +768,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- unsigned scanout_id = drmmode_crtc->scanout_id ^ info->tear_free;
+ unsigned scanout_id = 0;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
int saved_x, saved_y;
Rotation saved_rotation;
@@ -722,6 +812,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
if (!drmmode_handle_transform(crtc))
goto done;
+ drmmode_crtc_update_tear_free(crtc);
+ if (drmmode_crtc->tear_free)
+ scanout_id = drmmode_crtc->scanout_id;
+
crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
crtc->gamma_blue, crtc->gamma_size);
@@ -730,8 +824,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
fb_id = drmmode->fb_id;
#ifdef AMDGPU_PIXMAP_SHARING
if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
- fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
- x = y = 0;
+ drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
+ &fb_id, &x, &y);
} else
#endif
if (drmmode_crtc->rotate.fb_id) {
@@ -739,7 +833,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
x = y = 0;
} else if (!amdgpu_is_gpu_screen(pScreen) &&
- (info->tear_free ||
+ (drmmode_crtc->tear_free ||
#if XF86_CRTC_VERSION >= 4
crtc->driverIsPerformingTransform ||
#endif
@@ -828,6 +922,10 @@ done:
if (fb_id != drmmode_crtc->scanout[scanout_id].fb_id)
drmmode_crtc_scanout_free(drmmode_crtc);
+ else if (!drmmode_crtc->tear_free) {
+ drmmode_crtc_scanout_destroy(drmmode,
+ &drmmode_crtc->scanout[1]);
+ }
}
return ret;
@@ -1086,7 +1184,6 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
{
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
unsigned scanout_id = drmmode_crtc->scanout_id;
- AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
ScreenPtr screen = crtc->scrn->pScreen;
PixmapDirtyUpdatePtr dirty;
@@ -1107,7 +1204,7 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
ppix->drawable.height))
return FALSE;
- if (info->tear_free &&
+ if (drmmode_crtc->tear_free &&
!drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
ppix->drawable.width,
ppix->drawable.height)) {
@@ -1354,14 +1451,15 @@ static Bool drmmode_property_ignore(drmModePropertyPtr prop)
static void drmmode_output_create_resources(xf86OutputPtr output)
{
+ AMDGPUInfoPtr info = AMDGPUPTR(output->scrn);
drmmode_output_private_ptr drmmode_output = output->driver_private;
drmModeConnectorPtr mode_output = drmmode_output->mode_output;
AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(output->scrn);
- drmModePropertyPtr drmmode_prop;
+ drmModePropertyPtr drmmode_prop, tearfree_prop;
int i, j, err;
drmmode_output->props =
- calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
+ calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec));
if (!drmmode_output->props)
return;
@@ -1379,6 +1477,23 @@ static void drmmode_output_create_resources(xf86OutputPtr output)
j++;
}
+ /* Userspace-only property for TearFree */
+ tearfree_prop = calloc(1, sizeof(*tearfree_prop));
+ tearfree_prop->flags = DRM_MODE_PROP_ENUM;
+ strncpy(tearfree_prop->name, "TearFree", 8);
+ tearfree_prop->count_enums = 3;
+ tearfree_prop->enums = calloc(tearfree_prop->count_enums,
+ sizeof(*tearfree_prop->enums));
+ strncpy(tearfree_prop->enums[0].name, "off", 3);
+ strncpy(tearfree_prop->enums[1].name, "on", 2);
+ tearfree_prop->enums[1].value = 1;
+ strncpy(tearfree_prop->enums[2].name, "auto", 4);
+ tearfree_prop->enums[2].value = 2;
+ drmmode_output->props[j].mode_prop = tearfree_prop;
+ drmmode_output->props[j].value = info->tear_free;
+ drmmode_output->tear_free = info->tear_free;
+ drmmode_output->num_props++;
+
for (i = 0; i < drmmode_output->num_props; i++) {
drmmode_prop_ptr p = &drmmode_output->props[i];
drmmode_prop = p->mode_prop;
@@ -1504,11 +1619,26 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property,
/* search for matching name string, then set its value down */
for (j = 0; j < p->mode_prop->count_enums; j++) {
if (!strcmp(p->mode_prop->enums[j].name, name)) {
- drmModeConnectorSetProperty(pAMDGPUEnt->fd,
- drmmode_output->output_id,
- p->mode_prop->prop_id,
- p->mode_prop->enums
- [j].value);
+ if (i == (drmmode_output->num_props - 1)) {
+ if (drmmode_output->tear_free != j) {
+ xf86CrtcPtr crtc = output->crtc;
+
+ drmmode_output->tear_free = j;
+ if (crtc) {
+ drmmode_set_mode_major(crtc,
+ &crtc->mode,
+ crtc->rotation,
+ crtc->x,
+ crtc->y);
+ }
+ }
+ } else {
+ drmModeConnectorSetProperty(pAMDGPUEnt->fd,
+ drmmode_output->output_id,
+ p->mode_prop->prop_id,
+ p->mode_prop->enums[j].value);
+ }
+
return TRUE;
}
}