27
27
#include <stdlib.h>
28
28
#include <string.h>
31
static unsigned short computeVal(NvCtrlAttributePrivateHandle *,
32
int, float, float, float);
34
#define RED RED_CHANNEL_INDEX
35
#define GREEN GREEN_CHANNEL_INDEX
36
#define BLUE BLUE_CHANNEL_INDEX
40
* XXX The XF86VidMode extension can block remote clients.
41
* Unfortunately, there doesn't seem to be a good way to determine if
42
* we're blocked or not. So, we temporarily plug in an error handler,
43
* and watch for the XF86VidModeClientNotLocal error code, set a flag
44
* indicating that we should not use the XF86VidMode extension, and
45
* then restore the previous error handler. Yuck.
47
* XXX Different versions of XFree86 trigger errors on different
48
* protocol; older versions trigger an error on
49
* XF86VidModeGetGammaRampSize(), but newer versions appear to only
50
* error on XF86VidModeSetGammaRamp().
53
static Bool vidModeBlocked = False;
54
static int vidModeErrorBase = 0;
55
static int (*prev_error_handler)(Display *, XErrorEvent *) = NULL;
57
static int vidModeErrorHandler(Display *dpy, XErrorEvent *err)
59
if (err->error_code == (XF86VidModeClientNotLocal + vidModeErrorBase)) {
60
vidModeBlocked = True;
62
if (prev_error_handler) prev_error_handler(dpy, err);
70
31
NvCtrlVidModeAttributes *
71
32
NvCtrlInitVidModeAttributes(NvCtrlAttributePrivateHandle *h)
73
34
NvCtrlVidModeAttributes *vm = NULL;
35
int event, error, size, permissions = 0;
77
38
/* Check parameters */
78
39
if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
82
ret = XF86VidModeQueryExtension(h->dpy, &event, &vidModeErrorBase);
83
if (ret != True) goto failed;
43
ret = XF86VidModeQueryExtension(h->dpy, &event, &error);
44
if (!ret) goto failed;
85
vm = malloc(sizeof(NvCtrlVidModeAttributes));
46
vm = calloc(1, sizeof(NvCtrlVidModeAttributes));
87
48
ret = XF86VidModeQueryVersion(h->dpy, &(vm->major_version), &(vm->minor_version));
88
if (ret != True) goto failed;
49
if (!ret) goto failed;
90
if (vm->major_version < VM_MINMAJOR || (vm->major_version == VM_MINMAJOR && vm->minor_version < VM_MINMINOR)) {
51
if (vm->major_version < VM_MINMAJOR ||
52
(vm->major_version == VM_MINMAJOR && vm->minor_version < VM_MINMINOR)) {
91
53
nv_warning_msg("The version of the XF86VidMode extension present "
92
54
"on this display (%d.%d) does not support updating "
93
55
"gamma ramps. If you'd like to be able to adjust "
94
56
"gamma ramps, please update your X server such that "
95
57
"the version of the XF86VidMode extension is %d.%d "
96
"or higher.", vm->major_version, vm->minor_version, VM_MINMAJOR, VM_MINMINOR);
101
* XXX setup an error handler to catch any errors caused by the
102
* VidMode extension blocking remote clients; we'll restore the
103
* original error handler below
106
prev_error_handler = XSetErrorHandler(vidModeErrorHandler);
108
ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &vm->n);
110
/* check if XF86VidModeGetGammaRampSize was blocked */
112
if (vidModeBlocked) {
116
if (ret != True) goto failed;
118
vm->lut[RED] = malloc(sizeof(unsigned short) * vm->n);
119
vm->lut[GREEN] = malloc(sizeof(unsigned short) * vm->n);
120
vm->lut[BLUE] = malloc(sizeof(unsigned short) * vm->n);
122
ret = XF86VidModeGetGammaRamp(h->dpy, h->target_id, vm->n, vm->lut[RED],
123
vm->lut[GREEN], vm->lut[BLUE]);
125
/* check if XF86VidModeGetGammaRamp was blocked */
127
if (vidModeBlocked) {
131
if (ret != True) goto failed;
134
* XXX Currently, XF86VidModeSetGammaRamp() is the only other
135
* XF86VidMode protocol we send, and depending on the XFree86
136
* version, it may induce an X error for remote clients. So, try
137
* sending it here to see if we get an error (yes, this is the
138
* data we just retrieved above from XF86VidModeGetGammaRamp).
139
* It's terrible that we have to do this.
142
ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, vm->n,
147
* sync the protocol stream to make sure we process any X error
151
XSync(h->dpy, False);
153
/* check if XF86VidModeSetGammaRamp was blocked */
155
if (vidModeBlocked) {
159
/* finally, restore the original error handler */
161
XSetErrorHandler(prev_error_handler);
164
* XXX can we initialize this to anything based on the current
168
for (i = RED; i <= BLUE; i++) {
169
vm->brightness[i] = BRIGHTNESS_DEFAULT;
170
vm->contrast[i] = CONTRAST_DEFAULT;
171
vm->gamma[i] = GAMMA_DEFAULT;
174
/* take log2 of vm->n to find the sigbits */
176
for (i = 0; ((vm->n >> i) > 0); i++);
183
nv_warning_msg("The VidMode extension is blocked for remote "
184
"clients. To allow remote VidMode clients, the "
185
"XF86Config option \"AllowNonLocalXvidtune\" must be "
186
"set in the ServerFlags section of the XF86Config "
58
"or higher.", vm->major_version, vm->minor_version,
59
VM_MINMAJOR, VM_MINMINOR);
63
ret = XF86VidModeGetPermissions(h->dpy, h->target_id, &permissions);
69
if (((permissions & XF86VM_READ_PERMISSION) == 0) ||
70
((permissions & XF86VM_WRITE_PERMISSION) == 0)) {
75
ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &size);
77
if (!ret) goto failed;
79
vm->lut[RED_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size);
80
vm->lut[GREEN_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size);
81
vm->lut[BLUE_CHANNEL_INDEX] = malloc(sizeof(unsigned short) * size);
83
if ((vm->lut[RED_CHANNEL_INDEX] == NULL) ||
84
(vm->lut[GREEN_CHANNEL_INDEX] == NULL) ||
85
(vm->lut[BLUE_CHANNEL_INDEX] == NULL)) {
89
vm->gammaRampSize = size;
91
ret = XF86VidModeGetGammaRamp(h->dpy, h->target_id, size,
92
vm->lut[RED_CHANNEL_INDEX],
93
vm->lut[GREEN_CHANNEL_INDEX],
94
vm->lut[BLUE_CHANNEL_INDEX]);
95
if (!ret) goto failed;
97
NvCtrlInitGammaInputStruct(&vm->gammaInput);
194
/* restore the original error handler, if we overrode it */
196
if (prev_error_handler) {
197
XSetErrorHandler(prev_error_handler);
198
prev_error_handler = NULL;
103
free(vm->lut[RED_CHANNEL_INDEX]);
104
free(vm->lut[GREEN_CHANNEL_INDEX]);
105
free(vm->lut[BLUE_CHANNEL_INDEX]);
245
150
* it to the X server.
248
ReturnStatus NvCtrlSetColorAttributes(NvCtrlAttributeHandle *handle,
252
unsigned int bitmask)
153
ReturnStatus NvCtrlVidModeSetColorAttributes(NvCtrlAttributePrivateHandle *h,
157
unsigned int bitmask)
257
NvCtrlAttributePrivateHandle *h;
259
h = (NvCtrlAttributePrivateHandle *) handle;
261
/* Check parameters */
262
161
if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
263
162
return NvCtrlBadHandle;
265
if (!h->vm) return NvCtrlMissingExtension;
267
/* clamp input, but only the input specified in the bitmask */
269
for (ch = RED; ch <= BLUE; ch++) {
270
if (bitmask & (1 << ch)) {
271
if (bitmask & CONTRAST_VALUE) {
272
if (c[ch] > CONTRAST_MAX) c[ch] = CONTRAST_MAX;
273
if (c[ch] < CONTRAST_MIN) c[ch] = CONTRAST_MIN;
275
if (bitmask & BRIGHTNESS_VALUE) {
276
if (b[ch] > BRIGHTNESS_MAX) b[ch] = BRIGHTNESS_MAX;
277
if (b[ch] < BRIGHTNESS_MIN) b[ch] = BRIGHTNESS_MIN;
279
if (bitmask & GAMMA_VALUE) {
280
if (g[ch] > GAMMA_MAX) g[ch] = GAMMA_MAX;
281
if (g[ch] < GAMMA_MIN) g[ch] = GAMMA_MIN;
286
/* assign specified values */
288
if (bitmask & CONTRAST_VALUE) {
289
if (bitmask & RED_CHANNEL) h->vm->contrast[RED] = c[RED];
290
if (bitmask & GREEN_CHANNEL) h->vm->contrast[GREEN] = c[GREEN];
291
if (bitmask & BLUE_CHANNEL) h->vm->contrast[BLUE] = c[BLUE];
294
if (bitmask & BRIGHTNESS_VALUE) {
295
if (bitmask & RED_CHANNEL) h->vm->brightness[RED] = b[RED];
296
if (bitmask & GREEN_CHANNEL) h->vm->brightness[GREEN] = b[GREEN];
297
if (bitmask & BLUE_CHANNEL) h->vm->brightness[BLUE] = b[BLUE];
300
if (bitmask & GAMMA_VALUE) {
301
if (bitmask & RED_CHANNEL) h->vm->gamma[RED] = g[RED];
302
if (bitmask & GREEN_CHANNEL) h->vm->gamma[GREEN] = g[GREEN];
303
if (bitmask & BLUE_CHANNEL) h->vm->gamma[BLUE] = g[BLUE];
306
for (ch = RED; ch <= BLUE; ch++) {
307
if ( !(bitmask & (1 << ch))) continue; /* don't update this channel */
308
for (i = 0; i < h->vm->n; i++) {
309
h->vm->lut[ch][i] = computeVal(h, i, h->vm->contrast[ch],
310
h->vm->brightness[ch],
315
ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, h->vm->n,
320
if (ret != True) return NvCtrlError;
322
return NvCtrlSuccess;
324
} /* NvCtrlSetColorAttribute() */
327
ReturnStatus NvCtrlGetColorRamp(NvCtrlAttributeHandle *handle,
328
unsigned int channel,
329
unsigned short **lut,
166
return NvCtrlMissingExtension;
169
NvCtrlAssignGammaInput(&h->vm->gammaInput, c, b, g, bitmask);
171
NvCtrlUpdateGammaRamp(&h->vm->gammaInput,
172
h->vm->gammaRampSize,
176
ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, h->vm->gammaRampSize,
177
h->vm->lut[RED_CHANNEL_INDEX],
178
h->vm->lut[GREEN_CHANNEL_INDEX],
179
h->vm->lut[BLUE_CHANNEL_INDEX]);
181
return ret ? NvCtrlSuccess : NvCtrlError;
185
ReturnStatus NvCtrlVidModeGetColorRamp(NvCtrlAttributePrivateHandle *h,
186
unsigned int channel,
187
unsigned short **lut,
332
NvCtrlAttributePrivateHandle *h;
334
h = (NvCtrlAttributePrivateHandle *) handle;
336
/* Check parameters */
337
190
if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
338
191
return NvCtrlBadHandle;
340
if (!h->vm) return NvCtrlMissingExtension;
194
return NvCtrlMissingExtension;
197
*n = h->vm->gammaRampSize;
344
199
switch (channel) {
345
case RED_CHANNEL: *lut = h->vm->lut[RED]; break;
346
case GREEN_CHANNEL: *lut = h->vm->lut[GREEN]; break;
347
case BLUE_CHANNEL: *lut = h->vm->lut[BLUE]; break;
200
case RED_CHANNEL: *lut = h->vm->lut[RED_CHANNEL_INDEX]; break;
201
case GREEN_CHANNEL: *lut = h->vm->lut[GREEN_CHANNEL_INDEX]; break;
202
case BLUE_CHANNEL: *lut = h->vm->lut[BLUE_CHANNEL_INDEX]; break;
348
203
default: return NvCtrlBadArgument;
351
206
return NvCtrlSuccess;
356
* computeVal() - compute the LUT entry given its index, and the
357
* contrast, brightness, and gamma.
359
static unsigned short computeVal(NvCtrlAttributePrivateHandle *h,
360
int i, float c, float b, float g)
362
double j, half, scale;
366
shift = 16 - h->vm->sigbits;
368
scale = (double) num / 3.0; /* how much brightness and contrast
377
half = ((double) num / 2.0) - 1.0;
379
j *= half / (half - c);
382
half = (double) num / 2.0;
384
j *= (half + c) / half;
388
if (j < 0.0) j = 0.0;
392
g = 1.0 / (double) g;
397
val = (int) (pow (j / (double)num, g) * (double)num + 0.5);
405
if (val > num) val = num;
406
if (val < 0) val = 0;
409
return (unsigned short) val;
415
210
* Get XF86 Video Mode String Attribute Values