From fa8385df8a1d90ec20981082f3836f18c3b43ca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 19 Nov 2018 20:56:17 -0600 Subject: [PATCH] xf86Crtc: keep transformation filters used by CRTCs around Make a temporary copy of the filter and restore it once we might need them, as they might get free'd by the server in the mean time. We keep the copy flag inside the transformation itself so that we don't need to do any ABI change. Fixes #14 --- hw/xfree86/modes/xf86Crtc.c | 71 +++++++++++++++++++++++++++++++++++-- randr/rrtransform.c | 4 +++ render/filter.c | 1 + render/picturestr.h | 1 + 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 37a45bb3a..a959e19a5 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -152,6 +152,7 @@ xf86CrtcDestroy(xf86CrtcPtr crtc) xf86_config->num_crtc--; break; } + RRTransformFini(&crtc->transform); free(crtc->params); free(crtc->gamma_red); free(crtc); @@ -260,6 +261,54 @@ xf86CrtcSetScreenSubpixelOrder(ScreenPtr pScreen) PictureSetSubpixelOrder(pScreen, subpixel_order); } +static Bool +xf86CrtcCopyTransformFilter(RRTransformPtr transform) +{ + PictFilterRec *filter; + PictFilterRec *filterCopy; + + filter = transform->filter; + if (filter->tempCopy) + return TRUE; + + filterCopy = malloc(sizeof(PictFilterRec)); + if (!filterCopy) + return FALSE; + + memcpy(filterCopy, filter, sizeof(PictFilterRec)); + filterCopy->name = strdup(filter->name); + filterCopy->tempCopy = TRUE; + + transform->filter = filterCopy; + return TRUE; +} + +static Bool +xf86CrtcTryRestoreTransformFilterCopy(ScreenPtr pScreen, RRTransformPtr transform) +{ + PictFilterPtr actualFilter; + PictFilterPtr filterCopy; + + if (!transform->filter->tempCopy) + return TRUE; + + filterCopy = transform->filter; + actualFilter = PictureFindFilter(pScreen, filterCopy->name, -1); + if (!actualFilter) { + if (PictureAddFilter(pScreen, filterCopy->name, + filterCopy->ValidateParams, + filterCopy->width, filterCopy->height) > -1) + actualFilter = PictureFindFilter(pScreen, filterCopy->name, -1); + } + + free(filterCopy->name); + free(filterCopy); + + transform->filter = actualFilter; + + return transform->filter != NULL; +} + /** * Sets the given video mode on the given crtc */ @@ -295,7 +344,8 @@ xf86CrtcSetModeTransform(xf86CrtcPtr crtc, DisplayModePtr mode, saved_x = crtc->x; saved_y = crtc->y; saved_rotation = crtc->rotation; - if (crtc->transformPresent) { + if (crtc->transformPresent && + xf86CrtcTryRestoreTransformFilterCopy(scrn->pScreen, &crtc->transform)) { RRTransformInit(&saved_transform); RRTransformCopy(&saved_transform, &crtc->transform); } @@ -774,6 +824,15 @@ xf86CrtcCloseScreen(ScreenPtr screen) xf86CrtcPtr crtc = config->crtc[c]; crtc->randr_crtc = NULL; + + if (crtc->transformPresent) { + if (!xf86CrtcCopyTransformFilter(&crtc->transform)) + crtc->transformPresent = FALSE; + } + if (crtc->desiredTransformPresent) { + if (!xf86CrtcCopyTransformFilter(&crtc->desiredTransform)) + crtc->desiredTransformPresent = FALSE; + } } screen->CloseScreen = config->CloseScreen; @@ -2822,12 +2881,17 @@ xf86SetDesiredModes(ScrnInfoPtr scrn) crtc->desiredTransformPresent = FALSE; crtc->desiredX = 0; crtc->desiredY = 0; + RRTransformFini(&crtc->desiredTransform); } - if (crtc->desiredTransformPresent) + if (crtc->desiredTransformPresent && + xf86CrtcTryRestoreTransformFilterCopy(scrn->pScreen, + &crtc->desiredTransform)) { transform = &crtc->desiredTransform; - else + } else { + crtc->desiredTransformPresent = FALSE; transform = NULL; + } if (xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation, transform, crtc->desiredX, crtc->desiredY)) { @@ -2968,6 +3032,7 @@ xf86SetSingleMode(ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation) crtc->desiredTransformPresent = FALSE; crtc->desiredX = 0; crtc->desiredY = 0; + RRTransformFini(&crtc->desiredTransform); } } xf86DisableUnusedFunctions(pScrn); diff --git a/randr/rrtransform.c b/randr/rrtransform.c index d32b43aa3..9431db4a9 100644 --- a/randr/rrtransform.c +++ b/randr/rrtransform.c @@ -37,6 +37,10 @@ RRTransformInit(RRTransformPtr transform) void RRTransformFini(RRTransformPtr transform) { + if (transform->filter && transform->filter->tempCopy) { + free(transform->filter->name); + free(transform->filter); + } free(transform->params); } diff --git a/render/filter.c b/render/filter.c index 2741f406c..c69c068df 100644 --- a/render/filter.c +++ b/render/filter.c @@ -157,6 +157,7 @@ PictureAddFilter(ScreenPtr pScreen, ps->filters[i].ValidateParams = ValidateParams; ps->filters[i].width = width; ps->filters[i].height = height; + ps->filters[i].tempCopy = FALSE; return id; } diff --git a/render/picturestr.h b/render/picturestr.h index dd25a272d..57f7a1406 100644 --- a/render/picturestr.h +++ b/render/picturestr.h @@ -168,6 +168,7 @@ typedef struct { int id; PictFilterValidateParamsProcPtr ValidateParams; int width, height; + Bool tempCopy; } PictFilterRec, *PictFilterPtr; #define PictFilterNearest 0