Hello, Here is a new version of my patch to display the current gamma and brightness.
It takes into account the comments from Yang with respect to the brightness not being correctly computed when gamma's are very different between colours. In addition, it also makes sure that when setting the gamma, the maximum value is really 65535, so it's much safer to detect clamped values, and the brightness of output will be almost a 256th better :-) Eric
From df86bb7133a0da3c638fcf0cdb84910bc84e2cb0 Mon Sep 17 00:00:00 2001 From: Eric Piel <[email protected]> Date: Sun, 10 Jan 2010 00:08:53 +0100 Subject: [PATCH] xrandr: get gamma and brightness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even in verbose query mode, gamma and brigthness were not displayed. That's because they are not stored in the server the same way they are specified on the command line: they are stored as 256 * 3 u16 while the command line is 3 + 1 floats. Still, this is useful info for the users, and they don't care about how it's stored in the server. So we do a regression over the values stored to recover info in the same way as on the command line: gamma and brightness. Also, make sure that when we set the gamma, the maximum value is 65535, needed to handle correctly the clamped values. Signed-off-by: Ãric Piel <[email protected]> --- xrandr.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- xrandr.man | 10 ++++-- 2 files changed, 105 insertions(+), 12 deletions(-) diff --git a/xrandr.c b/xrandr.c index 65e0623..019021b 100644 --- a/xrandr.c +++ b/xrandr.c @@ -943,6 +943,17 @@ output_is_primary(output_t *output) return False; } +/* Returns the index of the last value in an array < 65535 */ +static int +find_last_non_clamped(CARD16 array[], int size) { + int i; + for (i = size - 1; i > 0; i--) { + if (array[i] < 65535) + return i; + } + return 0; +} + static void set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info) { @@ -1055,6 +1066,81 @@ set_output_info (output_t *output, RROutput xid, XRROutputInfo *output_info) rotation_name (output->rotation), reflection_name (output->rotation)); + /* set gamma */ + if (!(output->changes & changes_gamma)) + { + if (output->crtc_info) { + crtc_t *crtc = output->crtc_info; + XRRCrtcGamma *gamma; + double i1, v1, i2, v2; + int size, middle, last_best, last_red, last_green, last_blue; + CARD16 *best_array; + + size = XRRGetCrtcGammaSize(dpy, crtc->crtc.xid); + if (!size) + fatal("output %s cannot get gamma size\n", output->output.string); + + gamma = XRRGetCrtcGamma(dpy, crtc->crtc.xid); + if (!gamma) + fatal("output %s cannot get gamma\n", output->output.string); + + /* + * Here is a bit tricky because gamma is a whole curve for each + * color. So, typically, we need to represent 3 * 256 values as 3 + 1 + * values. Therefore, we approximate the gamma curve (v) by supposing + * it always follows the way we set it: a power function (i^g) + * multiplied by a brightness (b). + * v = i^g * b + * so g = (ln(v) - ln(b))/ln(i) + * and b can be found using two points (v1,i1) and (v2, i2): + * b = e^((ln(v2)*ln(i1) - ln(v1)*ln(i2))/ln(i1/i2)) + * For the best resolution, we select i2 at the highest place not + * clamped and i1 at i2/2. Note that if i2 = 1 (as in most normal + * cases), then b = v2. + */ + last_red = find_last_non_clamped(gamma->red, size); + last_green = find_last_non_clamped(gamma->green, size); + last_blue = find_last_non_clamped(gamma->blue, size); + best_array = gamma->red; + last_best = last_red; + if (last_green > last_best) { + last_best = last_green; + best_array = gamma->green; + } + if (last_blue > last_best) { + last_best = last_blue; + best_array = gamma->blue; + } + if (last_best == 0) + last_best = 1; + + middle = last_best / 2; + i1 = (double)(middle + 1) / size; + v1 = (double)(best_array[middle]) / 65535; + i2 = (double)(last_best + 1) / size; + v2 = (double)(best_array[last_best]) / 65535; + if (v2 < 0.0001) { /* The screen is black */ + output->brightness = 0; + output->gamma.red = 1; + output->gamma.green = 1; + output->gamma.blue = 1; + } else { + if ((last_best + 1) == size) + output->brightness = v2; + else + output->brightness = exp((log(v2)*log(i1) - log(v1)*log(i2))/log(i1/i2)); + output->gamma.red = log((double)(gamma->red[last_red / 2]) / output->brightness + / 65535) / log((double)((last_red / 2) + 1) / size); + output->gamma.green = log((double)(gamma->green[last_green / 2]) / output->brightness + / 65535) / log((double)((last_green / 2) + 1) / size); + output->gamma.blue = log((double)(gamma->blue[last_blue / 2]) / output->brightness + / 65535) / log((double)((last_blue / 2) + 1) / size); + } + + XRRFreeGamma(gamma); + } + } + /* set transformation */ if (!(output->changes & changes_transform)) { @@ -1225,25 +1311,25 @@ set_gamma(void) for (i = 0; i < size; i++) { if (output->gamma.red == 1.0 && output->brightness == 1.0) - gamma->red[i] = i << 8; + gamma->red[i] = (i << 8) + i; else gamma->red[i] = dmin(pow((double)i/(double)(size - 1), - (double)output->gamma.red) * (double)(size - 1) - * (double)output->brightness * 256, 65535.0); + output->gamma.red) * output->brightness, + 1.0) * 65535.0; if (output->gamma.green == 1.0 && output->brightness == 1.0) - gamma->green[i] = i << 8; + gamma->green[i] = (i << 8) + i; else gamma->green[i] = dmin(pow((double)i/(double)(size - 1), - (double)output->gamma.green) * (double)(size - 1) - * (double)output->brightness * 256, 65535); + output->gamma.green) * output->brightness, + 1.0) * 65535.0; if (output->gamma.blue == 1.0 && output->brightness == 1.0) - gamma->blue[i] = i << 8; + gamma->blue[i] = (i << 8) + i; else gamma->blue[i] = dmin(pow((double)i/(double)(size - 1), - (double)output->gamma.blue) * (double)(size - 1) - * (double)output->brightness * 256, 65535); + output->gamma.blue) * output->brightness, + 1.0) * 65535.0; } XRRSetCrtcGamma(dpy, crtc->crtc.xid, gamma); @@ -2919,6 +3005,9 @@ main (int argc, char **argv) printf ("\tIdentifier: 0x%x\n", (int)output->output.xid); printf ("\tTimestamp: %d\n", (int)output_info->timestamp); printf ("\tSubpixel: %s\n", order[output_info->subpixel_order]); + printf ("\tGamma: %#.2g:%#.2g:%#.2g\n", + output->gamma.red, output->gamma.green, output->gamma.blue); + printf ("\tBrightness: %#.2g\n", output->brightness); printf ("\tClones: "); for (j = 0; j < output_info->nclone; j++) { diff --git a/xrandr.man b/xrandr.man index 335b7c0..aa1d9c5 100644 --- a/xrandr.man +++ b/xrandr.man @@ -105,7 +105,9 @@ Print out a summary of the usage and exit. Print out the RandR version reported by the X server and exit. .IP \-\-verbose Causes xrandr to be more verbose. When used with \-q (or without other -options), xrandr will display more information about the server state. When +options), xrandr will display more information about the server state. Please +note that the gamma and brightness informations are only approximations of the +complete color profile stored in the server. When used along with options that reconfigure the system, progress will be reported while executing the configuration changes. .IP "\-q, \-\-query" @@ -287,11 +289,13 @@ for some reason, this option can override the normal selection. .IP "\-\-gamma \fIred\fP:\fIgreen\fP:\fIblue\fP" Set the specified floating point values as gamma correction on the crtc currently attached to this output. Note that you cannot get two different values -for cloned outputs and that switching an output to another crtc doesn't change +for cloned outputs (i.e.: which share the same crtc) and that switching an output to another crtc doesn't change the crtc gamma corrections at all. .IP "\-\-brightness \fIbrightness\fP" Multiply the gamma values on the crtc currently attached to the output to specified floating value. Useful for overly bright or overly dim outputs. +However, this is a software only modification, if your hardware has support to +actually change the brightness, you will probably prefer to use \fBxbacklight\fR. .PP .SH "RandR version 1.1 options" These options are available for X servers supporting RandR version 1.1 or @@ -342,7 +346,7 @@ when the projector is slightly above the screen: xrandr --fb 1024x768 --output VGA --transform 1.24,0.16,-124,0,1.24,0,0,0.000316,1 .RE .SH "SEE ALSO" -Xrandr(3), cvt(1), xkeystone(1) +Xrandr(3), cvt(1), xkeystone(1), xbacklight(1) .SH AUTHORS Keith Packard, Open Source Technology Center, Intel Corporation. -- 1.6.6
_______________________________________________ xorg-devel mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-devel
