~ubuntu-branches/ubuntu/quantal/nvidia-settings/quantal

« back to all changes in this revision

Viewing changes to src/libXNVCtrlAttributes/NvCtrlAttributesVidMode.c

  • Committer: Package Import Robot
  • Author(s): Alberto Milone
  • Date: 2012-10-04 12:58:33 UTC
  • mfrom: (1.1.24)
  • Revision ID: package-import@ubuntu.com-20121004125833-h1r81skpfza8teae
Tags: 304.51-0ubuntu1
* New upstream release:
  - Fixed a bug that sometimes caused the display layout area
    of the nvidia-settings control panel to be laid out
    incorrectly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
3
3
 * and Linux systems.
4
4
 *
5
 
 * Copyright (C) 2004 NVIDIA Corporation.
 
5
 * Copyright (C) 2004,2012 NVIDIA Corporation.
6
6
 *
7
7
 * This program is free software; you can redistribute it and/or modify it
8
8
 * under the terms and conditions of the GNU General Public License,
26
26
 
27
27
#include <stdlib.h>
28
28
#include <string.h>
29
 
#include <math.h>
30
 
 
31
 
static unsigned short computeVal(NvCtrlAttributePrivateHandle *,
32
 
                                 int, float, float, float);
33
 
 
34
 
#define RED   RED_CHANNEL_INDEX
35
 
#define GREEN GREEN_CHANNEL_INDEX
36
 
#define BLUE  BLUE_CHANNEL_INDEX
37
 
 
38
 
 
39
 
/*
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.
46
 
 *
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().
51
 
 */
52
 
 
53
 
static Bool vidModeBlocked = False;
54
 
static int vidModeErrorBase = 0;
55
 
static int (*prev_error_handler)(Display *, XErrorEvent *) = NULL;
56
 
 
57
 
static int vidModeErrorHandler(Display *dpy, XErrorEvent *err)
58
 
{
59
 
    if (err->error_code == (XF86VidModeClientNotLocal + vidModeErrorBase)) {
60
 
        vidModeBlocked = True;
61
 
    } else {
62
 
        if (prev_error_handler) prev_error_handler(dpy, err);
63
 
    }
64
 
    
65
 
    return 1;
66
 
}
67
 
 
68
29
 
69
30
 
70
31
NvCtrlVidModeAttributes *
71
32
NvCtrlInitVidModeAttributes(NvCtrlAttributePrivateHandle *h)
72
33
{
73
34
    NvCtrlVidModeAttributes *vm = NULL;
74
 
    int ret, event, i;
75
 
    
 
35
    int event, error, size, permissions = 0;
 
36
    Bool ret;
76
37
 
77
38
    /* Check parameters */
78
39
    if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
79
40
        goto failed;
80
41
    }
81
42
 
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;
84
45
 
85
 
    vm = malloc(sizeof(NvCtrlVidModeAttributes));
 
46
    vm = calloc(1, sizeof(NvCtrlVidModeAttributes));
86
47
 
87
48
    ret = XF86VidModeQueryVersion(h->dpy, &(vm->major_version), &(vm->minor_version));
88
 
    if (ret != True) goto failed;
 
49
    if (!ret) goto failed;
89
50
 
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);
97
 
        goto failed;
98
 
    }
99
 
 
100
 
    /*
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
104
 
     */
105
 
    
106
 
    prev_error_handler = XSetErrorHandler(vidModeErrorHandler);
107
 
    
108
 
    ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &vm->n);
109
 
    
110
 
    /* check if XF86VidModeGetGammaRampSize was blocked */
111
 
    
112
 
    if (vidModeBlocked) {
113
 
        goto blocked;
114
 
    }
115
 
    
116
 
    if (ret != True) goto failed;
117
 
    
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);
121
 
    
122
 
    ret = XF86VidModeGetGammaRamp(h->dpy, h->target_id, vm->n, vm->lut[RED],
123
 
                                  vm->lut[GREEN], vm->lut[BLUE]);
124
 
    
125
 
    /* check if XF86VidModeGetGammaRamp was blocked */
126
 
 
127
 
    if (vidModeBlocked) {
128
 
        goto blocked;
129
 
    }
130
 
 
131
 
    if (ret != True) goto failed;
132
 
    
133
 
    /*
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.
140
 
     */
141
 
    
142
 
    ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, vm->n,
143
 
                                  vm->lut[RED],
144
 
                                  vm->lut[GREEN],
145
 
                                  vm->lut[BLUE]);
146
 
    /*
147
 
     * sync the protocol stream to make sure we process any X error
148
 
     * before continuing
149
 
     */
150
 
    
151
 
    XSync(h->dpy, False);
152
 
 
153
 
    /* check if XF86VidModeSetGammaRamp was blocked */
154
 
    
155
 
    if (vidModeBlocked) {
156
 
        goto blocked;
157
 
    }
158
 
    
159
 
    /* finally, restore the original error handler */
160
 
    
161
 
    XSetErrorHandler(prev_error_handler);
162
 
    
163
 
    /*
164
 
     * XXX can we initialize this to anything based on the current
165
 
     * ramps?
166
 
     */
167
 
            
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;
172
 
    }
173
 
    
174
 
    /* take log2 of vm->n to find the sigbits */
175
 
    
176
 
    for (i = 0; ((vm->n >> i) > 0); i++);
177
 
    vm->sigbits = i - 1;
178
 
    
179
 
    return (vm);
180
 
 
181
 
 blocked:
182
 
    
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 "
187
 
                   "file.");
188
 
    
189
 
    /* fall through */
 
58
                       "or higher.", vm->major_version, vm->minor_version,
 
59
                       VM_MINMAJOR, VM_MINMINOR);
 
60
        goto failed;
 
61
    }
 
62
 
 
63
    ret = XF86VidModeGetPermissions(h->dpy, h->target_id, &permissions);
 
64
 
 
65
    if (!ret) {
 
66
        goto failed;
 
67
    }
 
68
 
 
69
    if (((permissions & XF86VM_READ_PERMISSION) == 0) ||
 
70
        ((permissions & XF86VM_WRITE_PERMISSION) == 0)) {
 
71
        goto failed;
 
72
    }
 
73
 
 
74
 
 
75
    ret = XF86VidModeGetGammaRampSize(h->dpy, h->target_id, &size);
 
76
 
 
77
    if (!ret) goto failed;
 
78
 
 
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);
 
82
 
 
83
    if ((vm->lut[RED_CHANNEL_INDEX] == NULL) ||
 
84
        (vm->lut[GREEN_CHANNEL_INDEX] == NULL) ||
 
85
        (vm->lut[BLUE_CHANNEL_INDEX] == NULL)) {
 
86
        goto failed;
 
87
    }
 
88
 
 
89
    vm->gammaRampSize = size;
 
90
 
 
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;
 
96
 
 
97
    NvCtrlInitGammaInputStruct(&vm->gammaInput);
 
98
 
 
99
    return vm;
190
100
 
191
101
 failed:
192
 
    if (vm) free(vm);
193
 
 
194
 
    /* restore the original error handler, if we overrode it */
195
 
 
196
 
    if (prev_error_handler) {
197
 
        XSetErrorHandler(prev_error_handler);
198
 
        prev_error_handler = NULL;
 
102
    if (vm) {
 
103
        free(vm->lut[RED_CHANNEL_INDEX]);
 
104
        free(vm->lut[GREEN_CHANNEL_INDEX]);
 
105
        free(vm->lut[BLUE_CHANNEL_INDEX]);
 
106
        free(vm);
199
107
    }
200
108
 
201
109
    return NULL;
203
111
} /* NvCtrlInitVidModeAttributes() */
204
112
 
205
113
 
206
 
ReturnStatus NvCtrlGetColorAttributes(NvCtrlAttributeHandle *handle,
207
 
                                      float contrast[3],
208
 
                                      float brightness[3],
209
 
                                      float gamma[3])
 
114
ReturnStatus NvCtrlVidModeGetColorAttributes(NvCtrlAttributePrivateHandle *h,
 
115
                                             float contrast[3],
 
116
                                             float brightness[3],
 
117
                                             float gamma[3])
210
118
{
211
119
    int i;
212
 
    NvCtrlAttributePrivateHandle *h;
213
 
    
214
 
    h = (NvCtrlAttributePrivateHandle *) handle;
215
120
 
216
121
    if (!h->vm) return NvCtrlMissingExtension;
217
122
 
218
 
    for (i = RED; i <= BLUE; i++) {
219
 
        contrast[i]   = h->vm->contrast[i];
220
 
        brightness[i] = h->vm->brightness[i];
221
 
        gamma[i]      = h->vm->gamma[i];
 
123
    for (i = FIRST_COLOR_CHANNEL; i <= LAST_COLOR_CHANNEL; i++) {
 
124
        contrast[i]   = h->vm->gammaInput.contrast[i];
 
125
        brightness[i] = h->vm->gammaInput.brightness[i];
 
126
        gamma[i]      = h->vm->gammaInput.gamma[i];
222
127
    }
223
128
    
224
129
    return NvCtrlSuccess;
245
150
 * it to the X server.
246
151
 */
247
152
 
248
 
ReturnStatus NvCtrlSetColorAttributes(NvCtrlAttributeHandle *handle,
249
 
                                      float c[3],
250
 
                                      float b[3],
251
 
                                      float g[3],
252
 
                                      unsigned int bitmask)
 
153
ReturnStatus NvCtrlVidModeSetColorAttributes(NvCtrlAttributePrivateHandle *h,
 
154
                                             float c[3],
 
155
                                             float b[3],
 
156
                                             float g[3],
 
157
                                             unsigned int bitmask)
253
158
{
254
 
    int i, ch;
255
159
    Bool ret;
256
 
    
257
 
    NvCtrlAttributePrivateHandle *h;
258
 
 
259
 
    h = (NvCtrlAttributePrivateHandle *) handle;
260
 
 
261
 
    /* Check parameters */
 
160
 
262
161
    if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
263
162
        return NvCtrlBadHandle;
264
163
    }
265
 
    if (!h->vm) return NvCtrlMissingExtension;
266
 
 
267
 
    /* clamp input, but only the input specified in the bitmask */
268
 
    
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;
274
 
            }
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;
278
 
            }
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;
282
 
            }
283
 
        }
284
 
    }
285
 
    
286
 
    /* assign specified values */
287
 
 
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];
292
 
    }
293
 
 
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];
298
 
    }
299
 
    
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];
304
 
    }
305
 
 
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],
311
 
                                           h->vm->gamma[ch]);
312
 
        }
313
 
    }
314
 
    
315
 
    ret = XF86VidModeSetGammaRamp(h->dpy, h->target_id, h->vm->n,
316
 
                                  h->vm->lut[RED],
317
 
                                  h->vm->lut[GREEN],
318
 
                                  h->vm->lut[BLUE]);
319
 
    
320
 
    if (ret != True) return NvCtrlError;
321
 
 
322
 
    return NvCtrlSuccess;
323
 
    
324
 
} /* NvCtrlSetColorAttribute() */
325
 
 
326
 
 
327
 
ReturnStatus NvCtrlGetColorRamp(NvCtrlAttributeHandle *handle,
328
 
                                unsigned int channel,
329
 
                                unsigned short **lut,
330
 
                                int *n)
 
164
 
 
165
    if (!h->vm) {
 
166
        return NvCtrlMissingExtension;
 
167
    }
 
168
 
 
169
    NvCtrlAssignGammaInput(&h->vm->gammaInput, c, b, g, bitmask);
 
170
 
 
171
    NvCtrlUpdateGammaRamp(&h->vm->gammaInput,
 
172
                          h->vm->gammaRampSize,
 
173
                          h->vm->lut,
 
174
                          bitmask);
 
175
 
 
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]);
 
180
 
 
181
    return ret ? NvCtrlSuccess : NvCtrlError;
 
182
}
 
183
 
 
184
 
 
185
ReturnStatus NvCtrlVidModeGetColorRamp(NvCtrlAttributePrivateHandle *h,
 
186
                                       unsigned int channel,
 
187
                                       unsigned short **lut,
 
188
                                       int *n)
331
189
{
332
 
    NvCtrlAttributePrivateHandle *h;
333
 
 
334
 
    h = (NvCtrlAttributePrivateHandle *) handle;
335
 
 
336
 
    /* Check parameters */
337
190
    if (!h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) {
338
191
        return NvCtrlBadHandle;
339
192
    }
340
 
    if (!h->vm) return NvCtrlMissingExtension;
341
 
 
342
 
    *n = h->vm->n;
343
 
    
 
193
    if (!h->vm) {
 
194
        return NvCtrlMissingExtension;
 
195
    }
 
196
 
 
197
    *n = h->vm->gammaRampSize;
 
198
 
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;
349
204
    }
350
205
    
351
206
    return NvCtrlSuccess;
352
207
}
353
208
 
354
 
 
355
 
/*
356
 
 * computeVal() - compute the LUT entry given its index, and the
357
 
 * contrast, brightness, and gamma.
358
 
 */
359
 
static unsigned short computeVal(NvCtrlAttributePrivateHandle *h,
360
 
                                 int i, float c, float b, float g)
361
 
{
362
 
    double j, half, scale;
363
 
    int shift, val, num;
364
 
    
365
 
    num = h->vm->n - 1;
366
 
    shift = 16 - h->vm->sigbits;
367
 
    
368
 
    scale = (double) num / 3.0; /* how much brightness and contrast
369
 
                                   affect the value */
370
 
    j = (double) i;
371
 
    
372
 
    /* contrast */
373
 
 
374
 
    c *= scale;
375
 
 
376
 
    if (c > 0.0) {
377
 
        half = ((double) num / 2.0) - 1.0;
378
 
        j -= half;
379
 
        j *= half / (half - c);
380
 
        j += half;
381
 
    } else {
382
 
        half = (double) num / 2.0;
383
 
        j -= half;
384
 
        j *= (half + c) / half;
385
 
        j += half;
386
 
    }
387
 
    
388
 
    if (j < 0.0) j = 0.0;
389
 
            
390
 
    /* gamma */
391
 
 
392
 
    g = 1.0 / (double) g;
393
 
    
394
 
    if (g == 1.0) {
395
 
        val = (int) j;
396
 
    } else {
397
 
        val = (int) (pow (j / (double)num, g) * (double)num + 0.5);
398
 
    }
399
 
 
400
 
    /* brightness */
401
 
    
402
 
    b *= scale;
403
 
 
404
 
    val += (int)b;
405
 
    if (val > num) val = num;
406
 
    if (val < 0) val = 0;
407
 
    
408
 
    val <<= shift;
409
 
    return (unsigned short) val;
410
 
    
411
 
} /* computeVal() */
412
 
 
413
 
 
414
209
/*
415
210
 * Get XF86 Video Mode String Attribute Values
416
211
 */