From 9869ed6aad3ee6d4e5d70cd9e8631840709693cb Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Sat, 27 Feb 2016 18:20:38 +0900 Subject: WIP: xfree86/modes: Decouple RandR core and driver gamma ramp sizes --- hw/xfree86/common/xf86cmap.c | 5 +- hw/xfree86/modes/xf86Crtc.c | 109 ------------------------------ hw/xfree86/modes/xf86RandR12.c | 148 ++++++++++++++++++++++++++++------------- hw/xfree86/modes/xf86RandR12.h | 2 + 4 files changed, 106 insertions(+), 158 deletions(-) diff --git a/hw/xfree86/common/xf86cmap.c b/hw/xfree86/common/xf86cmap.c index 4b38c994e..b491d1868 100644 --- a/hw/xfree86/common/xf86cmap.c +++ b/hw/xfree86/common/xf86cmap.c @@ -187,9 +187,10 @@ xf86HandleColormaps(ScreenPtr pScreen, pScreen->InstallColormap = CMapInstallColormap; pScreen->StoreColors = CMapStoreColors; - if (xf86_crtc_supports_gamma(pScrn)) + if (xf86_crtc_supports_gamma(pScrn)) { pScrn->LoadPalette = xf86RandR12LoadPalette; - else + xf86RandR12InitGamma(pScrn, elements); + } else pScrn->LoadPalette = loadPalette; pScrn->SetOverscan = setOverscan; pScreenPriv->maxColors = maxColors; diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index c2f58ff0c..05dce52ac 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -2445,108 +2445,6 @@ xf86TargetUserpref(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, return FALSE; } -static Bool -xf86CrtcSetInitialGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, - float gamma_blue) -{ - int i, size = 256; - CARD16 *red, *green, *blue; - - red = xallocarray(size, 3 * sizeof(CARD16)); - green = red + size; - blue = green + size; - - /* Only cause warning if user wanted gamma to be set. */ - if (!crtc->funcs->gamma_set && - (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0)) { - free(red); - return FALSE; - } - else if (!crtc->funcs->gamma_set) { - free(red); - return TRUE; - } - - /* At this early stage none of the randr-interface stuff is up. - * So take the default gamma size for lack of something better. - */ - for (i = 0; i < size; i++) { - if (gamma_red == 1.0) - red[i] = i << 8; - else - red[i] = (CARD16) (pow((double) i / (double) (size - 1), - 1. / (double) gamma_red) * (double) (size - - 1) * - 256); - - if (gamma_green == 1.0) - green[i] = i << 8; - else - green[i] = (CARD16) (pow((double) i / (double) (size - 1), - 1. / (double) gamma_green) * - (double) (size - 1) * 256); - - if (gamma_blue == 1.0) - blue[i] = i << 8; - else - blue[i] = (CARD16) (pow((double) i / (double) (size - 1), - 1. / (double) gamma_blue) * (double) (size - - 1) * - 256); - } - - /* Default size is 256, so anything else is failure. */ - if (size != crtc->gamma_size) { - free(red); - return FALSE; - } - - crtc->gamma_size = size; - memcpy(crtc->gamma_red, red, crtc->gamma_size * sizeof(CARD16)); - memcpy(crtc->gamma_green, green, crtc->gamma_size * sizeof(CARD16)); - memcpy(crtc->gamma_blue, blue, crtc->gamma_size * sizeof(CARD16)); - - /* Do not set gamma now, delay until the crtc is activated. */ - - free(red); - - return TRUE; -} - -static Bool -xf86OutputSetInitialGamma(xf86OutputPtr output) -{ - XF86ConfMonitorPtr mon = output->conf_monitor; - float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; - - if (!mon) - return TRUE; - - if (!output->crtc) - return FALSE; - - /* Get configured values, where they exist. */ - if (mon->mon_gamma_red >= GAMMA_MIN && mon->mon_gamma_red <= GAMMA_MAX) - gamma_red = mon->mon_gamma_red; - - if (mon->mon_gamma_green >= GAMMA_MIN && mon->mon_gamma_green <= GAMMA_MAX) - gamma_green = mon->mon_gamma_green; - - if (mon->mon_gamma_blue >= GAMMA_MIN && mon->mon_gamma_blue <= GAMMA_MAX) - gamma_blue = mon->mon_gamma_blue; - - /* This avoids setting gamma 1.0 in case another cloned output on this crtc has a specific gamma. */ - if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, - "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", - output->name, gamma_red, gamma_green, gamma_blue); - return xf86CrtcSetInitialGamma(output->crtc, gamma_red, gamma_green, - gamma_blue); - } - else - return TRUE; -} - /** * Construct default screen configuration * @@ -2666,9 +2564,6 @@ xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow) crtc->enabled = FALSE; memset(&crtc->desiredMode, '\0', sizeof(crtc->desiredMode)); - /* Set default gamma for all crtc's. */ - /* This is done to avoid problems later on with cloned outputs. */ - xf86CrtcSetInitialGamma(crtc, 1.0, 1.0, 1.0); } /* @@ -2693,10 +2588,6 @@ xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow) memcpy(crtc->panningBorder, output->initialBorder, 4 * sizeof(INT16)); output->crtc = crtc; - if (!xf86OutputSetInitialGamma(output)) - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Initial gamma correction for output %s: failed.\n", - output->name); } else { output->crtc = NULL; diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index e26eecd78..1f0088e31 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -1240,15 +1240,13 @@ static void xf86RandR12CrtcComputeGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) { xf86CrtcPtr crtc = randr_crtc->devPrivate; - int gamma_slots, gamma_ramp_size = xf86GetGammaRampSize(pScreen); + int gamma_slots; int i, j; gamma_slots = crtc->gamma_size / randr_crtc->paletteRedSize; for (i = 0; i < randr_crtc->paletteRedSize; i++) { j = i * gamma_slots; - crtc->gamma_red[j] = randr_crtc->gammaRed[randr_crtc->palette[i].red * - crtc->gamma_size / - gamma_ramp_size]; + crtc->gamma_red[j] = randr_crtc->gammaRed[randr_crtc->palette[i].red]; while (++j < (i + 1) * gamma_slots) crtc->gamma_red[j] = crtc->gamma_red[j - 1]; @@ -1257,9 +1255,7 @@ xf86RandR12CrtcComputeGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) gamma_slots = crtc->gamma_size / randr_crtc->paletteGreenSize; for (i = 0; i < randr_crtc->paletteGreenSize; i++) { j = i * gamma_slots; - crtc->gamma_green[j] = randr_crtc->gammaGreen[randr_crtc->palette[i].green * - crtc->gamma_size / - gamma_ramp_size]; + crtc->gamma_green[j] = randr_crtc->gammaGreen[randr_crtc->palette[i].green]; while (++j < (i + 1) * gamma_slots) crtc->gamma_green[j] = crtc->gamma_green[j - 1]; @@ -1268,9 +1264,7 @@ xf86RandR12CrtcComputeGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) gamma_slots = crtc->gamma_size / randr_crtc->paletteBlueSize; for (i = 0; i < randr_crtc->paletteBlueSize; i++) { j = i * gamma_slots; - crtc->gamma_blue[j] = randr_crtc->gammaBlue[randr_crtc->palette[i].blue * - crtc->gamma_size / - gamma_ramp_size]; + crtc->gamma_blue[j] = randr_crtc->gammaBlue[randr_crtc->palette[i].blue]; while (++j < (i + 1) * gamma_slots) crtc->gamma_blue[j] = crtc->gamma_blue[j - 1]; @@ -1301,60 +1295,121 @@ xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) if (crtc->funcs->gamma_set == NULL) return FALSE; - /* Realloc local gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; - - 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; - crtc->gamma_size = randr_crtc->gammaSize; + if (randr_crtc->paletteSize) { + xf86RandR12CrtcComputeGamma(pScreen, randr_crtc); + xf86RandR12CrtcResetGamma(randr_crtc); } - xf86RandR12CrtcComputeGamma(pScreen, randr_crtc); - xf86RandR12CrtcResetGamma(randr_crtc); - return TRUE; } static Bool xf86RandR12CrtcGetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc) { - xf86CrtcPtr crtc = randr_crtc->devPrivate; + return TRUE; +} - if (!crtc->gamma_size) - return FALSE; +static void +init_one_component(CARD16 *comp, unsigned size, unsigned shift, float gamma) +{ + int i; + + if (gamma == 1.0) { + for (i = 0; i < size; i++) + comp[i] = i << shift; + } else { + for (i = 0; i < size; i++) + comp[i] = (CARD16) (pow((double) i / (double) (size - 1), + 1. / (double) gamma) * + (double) (size - 1) * (1 << shift)); + } +} - if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) +static Bool +xf86RandR12CrtcInitGamma(xf86CrtcPtr crtc, float gamma_red, float gamma_green, + float gamma_blue) +{ + unsigned size = crtc->randr_crtc->gammaSize, shift; + CARD16 *red, *green, *blue; + + red = xallocarray(size, 3 * sizeof(CARD16)); + if (!red) return FALSE; - /* Realloc randr gamma if needed. */ - if (randr_crtc->gammaSize != crtc->gamma_size) { - CARD16 *tmp_ptr; + green = red + size; + blue = green + size; - tmp_ptr = reallocarray(randr_crtc->gammaRed, - crtc->gamma_size, 3 * sizeof(CARD16)); - if (!tmp_ptr) - return FALSE; - randr_crtc->gammaRed = tmp_ptr; - randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; - randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; + for (shift = 0; (size << shift) < (1 << 16); shift++); + + init_one_component(red, size, shift, gamma_red); + init_one_component(green, size, shift, gamma_green); + init_one_component(blue, size, shift, gamma_blue); + + RRCrtcGammaSet(crtc->randr_crtc, red, green, blue); + + return TRUE; +} + +static Bool +xf86RandR12OutputInitGamma(xf86OutputPtr output) +{ + XF86ConfMonitorPtr mon = output->conf_monitor; + float gamma_red = 1.0, gamma_green = 1.0, gamma_blue = 1.0; + + if (!mon) + return TRUE; + + /* Get configured values, where they exist. */ + if (mon->mon_gamma_red >= GAMMA_MIN && mon->mon_gamma_red <= GAMMA_MAX) + gamma_red = mon->mon_gamma_red; + + if (mon->mon_gamma_green >= GAMMA_MIN && mon->mon_gamma_green <= GAMMA_MAX) + gamma_green = mon->mon_gamma_green; + + if (mon->mon_gamma_blue >= GAMMA_MIN && mon->mon_gamma_blue <= GAMMA_MAX) + gamma_blue = mon->mon_gamma_blue; + + /* Don't set gamma 1.0 if another cloned output on this CRTC already set a + * different gamma + */ + if (gamma_red != 1.0 || gamma_green != 1.0 || gamma_blue != 1.0) { + xf86DrvMsg(output->scrn->scrnIndex, X_INFO, + "Output %s wants gamma correction (%.1f, %.1f, %.1f)\n", + output->name, gamma_red, gamma_green, gamma_blue); + return xf86RandR12CrtcInitGamma(output->crtc, gamma_red, gamma_green, + gamma_blue); } - randr_crtc->gammaSize = crtc->gamma_size; - memcpy(randr_crtc->gammaRed, crtc->gamma_red, - crtc->gamma_size * sizeof(CARD16)); - memcpy(randr_crtc->gammaGreen, crtc->gamma_green, - crtc->gamma_size * sizeof(CARD16)); - memcpy(randr_crtc->gammaBlue, crtc->gamma_blue, - crtc->gamma_size * sizeof(CARD16)); return TRUE; } +void +xf86RandR12InitGamma(ScrnInfoPtr pScrn, unsigned gammaSize) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + + /* Set default gamma for all CRTCs + * This is done to avoid problems later on with cloned outputs + */ + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcGammaSetSize(crtc->randr_crtc, gammaSize); + xf86RandR12CrtcInitGamma(crtc, 1.0, 1.0, 1.0); + } + + /* Set initial gamma per monitor configuration + */ + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; + + if (output->crtc && !xf86RandR12OutputInitGamma(output)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Initial gamma correction for output %s: failed.\n", + output->name); + } +} + static Bool xf86RandR12OutputSetProperty(ScreenPtr pScreen, RROutputPtr randr_output, @@ -1575,7 +1630,6 @@ xf86RandR12CreateObjects12(ScreenPtr pScreen) xf86CrtcPtr crtc = config->crtc[c]; crtc->randr_crtc = RRCrtcCreate(pScreen, crtc); - RRCrtcGammaSetSize(crtc->randr_crtc, 256); } /* * Configure outputs diff --git a/hw/xfree86/modes/xf86RandR12.h b/hw/xfree86/modes/xf86RandR12.h index 8b4219c2d..fbdfe75b4 100644 --- a/hw/xfree86/modes/xf86RandR12.h +++ b/hw/xfree86/modes/xf86RandR12.h @@ -42,5 +42,7 @@ extern _X_EXPORT void xf86RandR12TellChanged(ScreenPtr pScreen); extern _X_EXPORT void xf86RandR12LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual); +extern _X_EXPORT void xf86RandR12InitGamma(ScrnInfoPtr pScrn, + unsigned gammaSize); #endif /* _XF86_RANDR_H_ */ -- cgit v1.2.3