On Tue, Jun 21, 2016 at 11:12 PM, Michel Dänzer <mic...@daenzer.net> wrote: > From: Michel Dänzer <michel.daen...@amd.com> > > Instead of breaking the former when the driver supports the latter, > hook them up so that the hardware LUTs reflect the combination of the > current colourmap and gamma states. I.e. combine the colourmap, the > global gamma value/ramp and the RandR 1.2 per-CRTC gamma ramps into one > combined LUT per CRTC. > > Fixes e.g. gamma sliders not working in games. > > Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=27222 > Signed-off-by: Michel Dänzer <michel.daen...@amd.com> > --- > > v3: Free randrp->palette in xf86RandR12CloseScreen, fixes memory leak.
Reviewed-by: Alex Deucher <alexander.deuc...@amd.com> > > hw/xfree86/common/xf86Helper.c | 7 +- > hw/xfree86/common/xf86cmap.c | 55 ++----------- > hw/xfree86/modes/xf86RandR12.c | 175 > +++++++++++++++++++++++++---------------- > hw/xfree86/modes/xf86RandR12.h | 5 ++ > 4 files changed, 119 insertions(+), 123 deletions(-) > > diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c > index bceb017..6f3a608 100644 > --- a/hw/xfree86/common/xf86Helper.c > +++ b/hw/xfree86/common/xf86Helper.c > @@ -54,7 +54,6 @@ > #include "xf86Xinput.h" > #include "xf86InPriv.h" > #include "mivalidate.h" > -#include "xf86Crtc.h" > > /* For xf86GetClocks */ > #if defined(CSRG_BASED) || defined(__GNU__) > @@ -908,11 +907,7 @@ xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma) > scrp->gamma.green = 1.0; > scrp->gamma.blue = 1.0; > } > - /* Pretend we succeeded if we support better a gamma system. > - * This avoids a confusing message. > - */ > - if (xf86_crtc_supports_gamma(scrp)) > - return TRUE; > + > xf86DrvMsg(scrp->scrnIndex, from, > "Using gamma correction (%.1f, %.1f, %.1f)\n", > scrp->gamma.red, scrp->gamma.green, scrp->gamma.blue); > diff --git a/hw/xfree86/common/xf86cmap.c b/hw/xfree86/common/xf86cmap.c > index ba0b277..1f21a0b 100644 > --- a/hw/xfree86/common/xf86cmap.c > +++ b/hw/xfree86/common/xf86cmap.c > @@ -49,6 +49,7 @@ > #include "xf86_OSproc.h" > #include "xf86str.h" > #include "micmap.h" > +#include "xf86RandR12.h" > #include "xf86Crtc.h" > > #ifdef XFreeXDGA > @@ -132,9 +133,6 @@ static void CMapUnwrapScreen(ScreenPtr pScreen); > Bool > xf86ColormapAllocatePrivates(ScrnInfoPtr pScrn) > { > - /* If we support a better colormap system, then pretend we succeeded. */ > - if (xf86_crtc_supports_gamma(pScrn)) > - return TRUE; > if (!dixRegisterPrivateKey(&CMapScreenKeyRec, PRIVATE_SCREEN, 0)) > return FALSE; > > @@ -157,10 +155,6 @@ xf86HandleColormaps(ScreenPtr pScreen, > int *indices; > int elements; > > - /* If we support a better colormap system, then pretend we succeeded. */ > - if (xf86_crtc_supports_gamma(pScrn)) > - return TRUE; > - > if (!maxColors || !sigRGBbits || !loadPalette) > return FALSE; > > @@ -193,7 +187,12 @@ xf86HandleColormaps(ScreenPtr pScreen, > pScreen->InstallColormap = CMapInstallColormap; > pScreen->StoreColors = CMapStoreColors; > > - pScrn->LoadPalette = loadPalette; > + if (xf86_crtc_supports_gamma(pScrn)) { > + pScrn->LoadPalette = xf86RandR12LoadPalette; > + if (!xf86RandR12InitGamma(pScrn, elements)) > + return FALSE; > + } else > + pScrn->LoadPalette = loadPalette; > pScrn->SetOverscan = setOverscan; > pScreenPriv->maxColors = maxColors; > pScreenPriv->sigRGBbits = sigRGBbits; > @@ -1005,19 +1004,6 @@ xf86ChangeGammaRamp(ScreenPtr pScreen, > CMapScreenPtr pScreenPriv; > CMapLinkPtr pLink; > > - if (xf86_crtc_supports_gamma(pScrn)) { > - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); > - > - if (crtc) { > - if (crtc->gammaSize != size) > - return BadValue; > - > - RRCrtcGammaSet(crtc, red, green, blue); > - > - return Success; > - } > - } > - > if (!CMapScreenKeyRegistered) > return BadImplementation; > > @@ -1077,16 +1063,8 @@ xf86ChangeGammaRamp(ScreenPtr pScreen, > int > xf86GetGammaRampSize(ScreenPtr pScreen) > { > - ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); > CMapScreenPtr pScreenPriv; > > - if (xf86_crtc_supports_gamma(pScrn)) { > - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); > - > - if (crtc) > - return crtc->gammaSize; > - } > - > if (!CMapScreenKeyRegistered) > return 0; > > @@ -1104,29 +1082,10 @@ xf86GetGammaRamp(ScreenPtr pScreen, > unsigned short *red, > unsigned short *green, unsigned short *blue) > { > - ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); > CMapScreenPtr pScreenPriv; > LOCO *entry; > int shift, sigbits; > > - if (xf86_crtc_supports_gamma(pScrn)) { > - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); > - > - if (crtc) { > - if (crtc->gammaSize < size) > - return BadValue; > - > - if (!RRCrtcGammaGet(crtc)) > - return BadImplementation; > - > - memcpy(red, crtc->gammaRed, size * sizeof(*red)); > - memcpy(green, crtc->gammaGreen, size * sizeof(*green)); > - memcpy(blue, crtc->gammaBlue, size * sizeof(*blue)); > - > - return Success; > - } > - } > - > if (!CMapScreenKeyRegistered) > return BadImplementation; > > diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c > index e8a62e8..bcf4176 100644 > --- a/hw/xfree86/modes/xf86RandR12.c > +++ b/hw/xfree86/modes/xf86RandR12.c > @@ -40,6 +40,7 @@ > #include <randrstr.h> > #include <X11/extensions/render.h> > > +#include "xf86cmap.h" > #include "xf86Crtc.h" > #include "xf86RandR12.h" > > @@ -55,6 +56,13 @@ typedef struct _xf86RandR12Info { > Rotation rotation; /* current mode */ > Rotation supported_rotations; /* driver supported */ > > + /* Compatibility with colormaps and XF86VidMode's gamma */ > + int palette_red_size; > + int palette_green_size; > + int palette_blue_size; > + int palette_size; > + LOCO *palette; > + > /* Used to wrap EnterVT so we can re-probe the outputs when a laptop > unsuspends > * (actually, any time that we switch back into our VT). > * > @@ -882,6 +890,9 @@ xf86RandR12Init(ScreenPtr pScreen) > > randrp->maxX = randrp->maxY = 0; > > + randrp->palette_size = 0; > + randrp->palette = NULL; > + > dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); > > #if RANDR_12_INTERFACE > @@ -905,6 +916,7 @@ xf86RandR12CloseScreen(ScreenPtr pScreen) > pScreen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder; > #endif > > + free(randrp->palette); > free(randrp); > } > > @@ -1235,37 +1247,49 @@ xf86RandR12CrtcSet(ScreenPtr pScreen, > return xf86RandR12CrtcNotify(randr_crtc); > } > > -static Bool > -xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) > +static void > +xf86RandR12CrtcComputeGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) > { > + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); > xf86CrtcPtr crtc = randr_crtc->devPrivate; > + int gamma_slots; > + int i, j; > > - if (crtc->funcs->gamma_set == NULL) > - return FALSE; > + gamma_slots = crtc->gamma_size / randrp->palette_red_size; > + for (i = 0; i < randrp->palette_red_size; i++) { > + j = i * gamma_slots; > + crtc->gamma_red[j] = randr_crtc->gammaRed[randrp->palette[i].red]; > > - if (!crtc->scrn->vtSema) > - return TRUE; > + while (++j < (i + 1) * gamma_slots) > + crtc->gamma_red[j] = crtc->gamma_red[j - 1]; > + } > > - /* Realloc local gamma if needed. */ > - if (randr_crtc->gammaSize != crtc->gamma_size) { > - CARD16 *tmp_ptr; > + gamma_slots = crtc->gamma_size / randrp->palette_green_size; > + for (i = 0; i < randrp->palette_green_size; i++) { > + j = i * gamma_slots; > + crtc->gamma_green[j] = > randr_crtc->gammaGreen[randrp->palette[i].green]; > > - tmp_ptr = reallocarray(crtc->gamma_red, > - randr_crtc->gammaSize, 3 * sizeof(CARD16)); > - if (!tmp_ptr) > - return FALSE; > - crtc->gamma_red = tmp_ptr; > - crtc->gamma_green = crtc->gamma_red + randr_crtc->gammaSize; > - crtc->gamma_blue = crtc->gamma_green + randr_crtc->gammaSize; > + while (++j < (i + 1) * gamma_slots) > + crtc->gamma_green[j] = crtc->gamma_green[j - 1]; > } > > - crtc->gamma_size = randr_crtc->gammaSize; > - memcpy(crtc->gamma_red, randr_crtc->gammaRed, > - crtc->gamma_size * sizeof(CARD16)); > - memcpy(crtc->gamma_green, randr_crtc->gammaGreen, > - crtc->gamma_size * sizeof(CARD16)); > - memcpy(crtc->gamma_blue, randr_crtc->gammaBlue, > - crtc->gamma_size * sizeof(CARD16)); > + gamma_slots = crtc->gamma_size / randrp->palette_blue_size; > + for (i = 0; i < randrp->palette_blue_size; i++) { > + j = i * gamma_slots; > + crtc->gamma_blue[j] = randr_crtc->gammaBlue[randrp->palette[i].blue]; > + > + while (++j < (i + 1) * gamma_slots) > + crtc->gamma_blue[j] = crtc->gamma_blue[j - 1]; > + } > +} > + > +static void > +xf86RandR12CrtcReloadGamma(RRCrtcPtr randr_crtc) > +{ > + xf86CrtcPtr crtc = randr_crtc->devPrivate; > + > + if (!crtc->scrn->vtSema || !crtc->funcs->gamma_set) > + return; > > /* Only set it when the crtc is actually running. > * Otherwise it will be set when it's activated. > @@ -1273,6 +1297,21 @@ xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr > randr_crtc) > if (crtc->active) > crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, > crtc->gamma_blue, crtc->gamma_size); > +} > + > +static Bool > +xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) > +{ > + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); > + xf86CrtcPtr crtc = randr_crtc->devPrivate; > + > + if (crtc->funcs->gamma_set == NULL) > + return FALSE; > + > + if (randrp->palette_size) { > + xf86RandR12CrtcComputeGamma(pScreen, randr_crtc); > + xf86RandR12CrtcReloadGamma(randr_crtc); > + } > > return TRUE; > } > @@ -1352,7 +1391,7 @@ xf86RandR12OutputInitGamma(xf86OutputPtr output) > return TRUE; > } > > -static Bool > +Bool > xf86RandR12InitGamma(ScrnInfoPtr pScrn, unsigned gammaSize) { > xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); > int o, c; > @@ -1809,57 +1848,56 @@ xf86RandR13SetPanning(ScreenPtr pScreen, > } > > /* > - * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers > - * any per-crtc setup. You asked for it... > + * Compatibility with colormaps and XF86VidMode's gamma > */ > - > -static void > -gamma_to_ramp(float gamma, CARD16 *ramp, int size) > +void > +xf86RandR12LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, > + LOCO *colors, VisualPtr pVisual) > { > - int i; > + ScreenPtr pScreen = pScrn->pScreen; > + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); > + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); > + int reds, greens, blues, index, palette_size; > + int c, i; > > - for (i = 0; i < size; i++) { > - if (gamma == 1.0) > - ramp[i] = i | i << 8; > - else > - ramp[i] = > - (CARD16) (pow((double) i / (double) (size - 1), 1. / gamma) > - * (double) (size - 1) * 257); > + if (pVisual->class == TrueColor || pVisual->class == DirectColor) { > + reds = (pVisual->redMask >> pVisual->offsetRed) + 1; > + greens = (pVisual->greenMask >> pVisual->offsetGreen) + 1; > + blues = (pVisual->blueMask >> pVisual->offsetBlue) + 1; > + } else { > + reds = greens = blues = pVisual->ColormapEntries; > } > -} > - > -static int > -xf86RandR12ChangeGamma(ScrnInfoPtr pScrn, Gamma gamma) > -{ > - CARD16 *points, *red, *green, *blue; > - RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); > - int size; > - > - if (!crtc) > - return Success; > - > - size = max(0, crtc->gammaSize); > - if (!size) > - return Success; > > - points = calloc(size, 3 * sizeof(CARD16)); > - if (!points) > - return BadAlloc; > + palette_size = max(reds, max(greens, blues)); > > - red = points; > - green = points + size; > - blue = points + 2 * size; > - > - gamma_to_ramp(gamma.red, red, size); > - gamma_to_ramp(gamma.green, green, size); > - gamma_to_ramp(gamma.blue, blue, size); > - RRCrtcGammaSet(crtc, red, green, blue); > - > - free(points); > + for (c = 0; c < config->num_crtc; c++) { > + xf86CrtcPtr crtc = config->crtc[c]; > + RRCrtcPtr randr_crtc = crtc->randr_crtc; > > - pScrn->gamma = gamma; > + if (randrp->palette_size != palette_size) { > + randrp->palette = > + reallocarray(randrp->palette, palette_size, > + sizeof(colors[0])); > + randrp->palette_size = palette_size; > + } > + randrp->palette_red_size = reds; > + randrp->palette_green_size = greens; > + randrp->palette_blue_size = blues; > + > + for (i = 0; i < numColors; i++) { > + index = indices[i]; > + > + if (index < reds) > + randrp->palette[index].red = colors[index].red; > + if (index < greens) > + randrp->palette[index].green = colors[index].green; > + if (index < blues) > + randrp->palette[index].blue = colors[index].blue; > + } > > - return Success; > + xf86RandR12CrtcComputeGamma(pScreen, randr_crtc); > + xf86RandR12CrtcReloadGamma(randr_crtc); > + } > } > > static Bool > @@ -1882,7 +1920,7 @@ xf86RandR12EnterVT(ScrnInfoPtr pScrn) > > /* reload gamma */ > for (i = 0; i < rp->numCrtcs; i++) > - xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]); > + xf86RandR12CrtcReloadGamma(rp->crtcs[i]); > > return RRGetInfo(pScreen, TRUE); /* force a re-probe of outputs and > notify clients about changes */ > } > @@ -2061,7 +2099,6 @@ xf86RandR12Init12(ScreenPtr pScreen) > rp->rrProviderDestroy = xf86RandR14ProviderDestroy; > > pScrn->PointerMoved = xf86RandR12PointerMoved; > - pScrn->ChangeGamma = xf86RandR12ChangeGamma; > > randrp->orig_EnterVT = pScrn->EnterVT; > pScrn->EnterVT = xf86RandR12EnterVT; > diff --git a/hw/xfree86/modes/xf86RandR12.h b/hw/xfree86/modes/xf86RandR12.h > index e603799..31aaaaf 100644 > --- a/hw/xfree86/modes/xf86RandR12.h > +++ b/hw/xfree86/modes/xf86RandR12.h > @@ -40,4 +40,9 @@ extern _X_EXPORT void > xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, > extern _X_EXPORT Bool xf86RandR12PreInit(ScrnInfoPtr pScrn); > extern _X_EXPORT void xf86RandR12TellChanged(ScreenPtr pScreen); > > +extern void xf86RandR12LoadPalette(ScrnInfoPtr pScrn, int numColors, > + int *indices, LOCO *colors, > + VisualPtr pVisual); > +extern Bool xf86RandR12InitGamma(ScrnInfoPtr pScrn, unsigned gammaSize); > + > #endif /* _XF86_RANDR_H_ */ > -- > 2.8.1 > > _______________________________________________ > xorg-devel@lists.x.org: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: https://lists.x.org/mailman/listinfo/xorg-devel _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel