xf86VidMode.c revision 35c4bbdf
1/*
2 * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * This file contains the VidMode functions required by the extension.
30 * These have been added to avoid the need for the higher level extension
31 * code to access the private XFree86 data structures directly. Wherever
32 * possible this code uses the functions in xf86Mode.c to do the work,
33 * so that two version of code that do similar things don't have to be
34 * maintained.
35 */
36
37#ifdef HAVE_XORG_CONFIG_H
38#include <xorg-config.h>
39#endif
40
41#include <X11/X.h>
42#include "os.h"
43#include "xf86.h"
44#include "xf86Priv.h"
45#include "extinit.h"
46
47#ifdef XF86VIDMODE
48#include "vidmodestr.h"
49#include "xf86Privstr.h"
50#include "xf86Extensions.h"
51#include "xf86cmap.h"
52
53static vidMonitorValue
54xf86VidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
55{
56    vidMonitorValue ret = { NULL, };
57    MonPtr monitor;
58    ScrnInfoPtr pScrn;
59
60    pScrn = xf86ScreenToScrn(pScreen);
61    monitor = pScrn->monitor;
62
63    switch (valtyp) {
64    case VIDMODE_MON_VENDOR:
65        ret.ptr = monitor->vendor;
66        break;
67    case VIDMODE_MON_MODEL:
68        ret.ptr = monitor->model;
69        break;
70    case VIDMODE_MON_NHSYNC:
71        ret.i = monitor->nHsync;
72        break;
73    case VIDMODE_MON_NVREFRESH:
74        ret.i = monitor->nVrefresh;
75        break;
76    case VIDMODE_MON_HSYNC_LO:
77        ret.f = (100.0 * monitor->hsync[indx].lo);
78        break;
79    case VIDMODE_MON_HSYNC_HI:
80        ret.f = (100.0 * monitor->hsync[indx].hi);
81        break;
82    case VIDMODE_MON_VREFRESH_LO:
83        ret.f = (100.0 * monitor->vrefresh[indx].lo);
84        break;
85    case VIDMODE_MON_VREFRESH_HI:
86        ret.f = (100.0 * monitor->vrefresh[indx].hi);
87        break;
88    }
89    return ret;
90}
91
92static Bool
93xf86VidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
94{
95    ScrnInfoPtr pScrn;
96
97    pScrn = xf86ScreenToScrn(pScreen);
98
99    if (pScrn->currentMode) {
100        *mode = pScrn->currentMode;
101        *dotClock = pScrn->currentMode->Clock;
102
103        return TRUE;
104    }
105    return FALSE;
106}
107
108static int
109xf86VidModeGetDotClock(ScreenPtr pScreen, int Clock)
110{
111    ScrnInfoPtr pScrn;
112
113    pScrn = xf86ScreenToScrn(pScreen);
114    if ((pScrn->progClock) || (Clock >= MAXCLOCKS))
115        return Clock;
116    else
117        return pScrn->clock[Clock];
118}
119
120static int
121xf86VidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock)
122{
123    ScrnInfoPtr pScrn;
124
125    pScrn = xf86ScreenToScrn(pScreen);
126    if (pScrn->progClock) {
127        *progClock = TRUE;
128        return 0;
129    }
130    else {
131        *progClock = FALSE;
132        return pScrn->numClocks;
133    }
134}
135
136static Bool
137xf86VidModeGetClocks(ScreenPtr pScreen, int *Clocks)
138{
139    ScrnInfoPtr pScrn;
140    int i;
141
142    pScrn = xf86ScreenToScrn(pScreen);
143
144    if (pScrn->progClock)
145        return FALSE;
146
147    for (i = 0; i < pScrn->numClocks; i++)
148        *Clocks++ = pScrn->clock[i];
149
150    return TRUE;
151}
152
153static Bool
154xf86VidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
155{
156    VidModePtr pVidMode;
157    DisplayModePtr p;
158
159    pVidMode = VidModeGetPtr(pScreen);
160
161    for (p = pVidMode->Next; p != NULL && p != pVidMode->First; p = p->next) {
162        if (p->status == MODE_OK) {
163            pVidMode->Next = p->next;
164            *mode = p;
165            *dotClock = xf86VidModeGetDotClock(pScreen, p->Clock);
166            return TRUE;
167        }
168    }
169
170    return FALSE;
171}
172
173static Bool
174xf86VidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
175{
176    ScrnInfoPtr pScrn;
177    VidModePtr pVidMode;
178
179    pScrn = xf86ScreenToScrn(pScreen);
180    if (pScrn->modes == NULL)
181        return FALSE;
182
183    pVidMode = VidModeGetPtr(pScreen);
184    pVidMode->First = pScrn->modes;
185    pVidMode->Next = pVidMode->First->next;
186
187    if (pVidMode->First->status == MODE_OK) {
188        *mode = pVidMode->First;
189        *dotClock = xf86VidModeGetDotClock(pScreen, pVidMode->First->Clock);
190        return TRUE;
191    }
192
193    return xf86VidModeGetNextModeline(pScreen, mode, dotClock);
194}
195
196static Bool
197xf86VidModeDeleteModeline(ScreenPtr pScreen, DisplayModePtr mode)
198{
199    ScrnInfoPtr pScrn;
200
201    if (mode == NULL)
202        return FALSE;
203
204    pScrn = xf86ScreenToScrn(pScreen);
205    xf86DeleteMode(&(pScrn->modes), mode);
206    return TRUE;
207}
208
209static Bool
210xf86VidModeZoomViewport(ScreenPtr pScreen, int zoom)
211{
212    xf86ZoomViewport(pScreen, zoom);
213    return TRUE;
214}
215
216static Bool
217xf86VidModeSetViewPort(ScreenPtr pScreen, int x, int y)
218{
219    ScrnInfoPtr pScrn;
220
221    pScrn = xf86ScreenToScrn(pScreen);
222    pScrn->frameX0 = min(max(x, 0),
223                         pScrn->virtualX - pScrn->currentMode->HDisplay);
224    pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
225    pScrn->frameY0 = min(max(y, 0),
226                         pScrn->virtualY - pScrn->currentMode->VDisplay);
227    pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
228    if (pScrn->AdjustFrame != NULL)
229        (pScrn->AdjustFrame) (pScrn, pScrn->frameX0, pScrn->frameY0);
230
231    return TRUE;
232}
233
234static Bool
235xf86VidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
236{
237    ScrnInfoPtr pScrn;
238
239    pScrn = xf86ScreenToScrn(pScreen);
240    *x = pScrn->frameX0;
241    *y = pScrn->frameY0;
242    return TRUE;
243}
244
245static Bool
246xf86VidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
247{
248    ScrnInfoPtr pScrn;
249    DisplayModePtr pTmpMode;
250    Bool retval;
251
252    pScrn = xf86ScreenToScrn(pScreen);
253    /* save in case we fail */
254    pTmpMode = pScrn->currentMode;
255    /* Force a mode switch */
256    pScrn->currentMode = NULL;
257    retval = xf86SwitchMode(pScrn->pScreen, mode);
258    /* we failed: restore it */
259    if (retval == FALSE)
260        pScrn->currentMode = pTmpMode;
261    return retval;
262}
263
264static Bool
265xf86VidModeLockZoom(ScreenPtr pScreen, Bool lock)
266{
267    if (xf86Info.dontZoom)
268        return FALSE;
269
270    xf86LockZoom(pScreen, lock);
271    return TRUE;
272}
273
274static ModeStatus
275xf86VidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
276{
277    ScrnInfoPtr pScrn;
278
279    if (mode == NULL)
280        return MODE_ERROR;
281
282    pScrn = xf86ScreenToScrn(pScreen);
283
284    return xf86CheckModeForMonitor(mode, pScrn->monitor);
285}
286
287static ModeStatus
288xf86VidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode)
289{
290    ScrnInfoPtr pScrn;
291
292    if (mode == NULL)
293        return MODE_ERROR;
294
295    pScrn = xf86ScreenToScrn(pScreen);
296
297    return xf86CheckModeForDriver(pScrn, mode, 0);
298}
299
300static void
301xf86VidModeSetCrtcForMode(ScreenPtr pScreen, DisplayModePtr mode)
302{
303    ScrnInfoPtr pScrn;
304    DisplayModePtr ScreenModes;
305
306    if (mode == NULL)
307        return;
308
309    /* Ugly hack so that the xf86Mode.c function can be used without change */
310    pScrn = xf86ScreenToScrn(pScreen);
311    ScreenModes = pScrn->modes;
312    pScrn->modes = mode;
313
314    xf86SetCrtcForModes(pScrn, pScrn->adjustFlags);
315    pScrn->modes = ScreenModes;
316    return;
317}
318
319static Bool
320xf86VidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode)
321{
322    ScrnInfoPtr pScrn;
323
324    if (mode == NULL)
325        return FALSE;
326
327    pScrn = xf86ScreenToScrn(pScreen);
328
329    mode->name = strdup(""); /* freed by deletemode */
330    mode->status = MODE_OK;
331    mode->next = pScrn->modes->next;
332    mode->prev = pScrn->modes;
333    pScrn->modes->next = mode;
334    if (mode->next != NULL)
335        mode->next->prev = mode;
336
337    return TRUE;
338}
339
340static int
341xf86VidModeGetNumOfModes(ScreenPtr pScreen)
342{
343    DisplayModePtr mode = NULL;
344    int dotClock = 0, nummodes = 0;
345
346    if (!xf86VidModeGetFirstModeline(pScreen, &mode, &dotClock))
347        return nummodes;
348
349    do {
350        nummodes++;
351        if (!xf86VidModeGetNextModeline(pScreen, &mode, &dotClock))
352            return nummodes;
353    } while (TRUE);
354}
355
356static Bool
357xf86VidModeSetGamma(ScreenPtr pScreen, float red, float green, float blue)
358{
359    Gamma gamma;
360
361    gamma.red = red;
362    gamma.green = green;
363    gamma.blue = blue;
364    if (xf86ChangeGamma(pScreen, gamma) != Success)
365        return FALSE;
366    else
367        return TRUE;
368}
369
370static Bool
371xf86VidModeGetGamma(ScreenPtr pScreen, float *red, float *green, float *blue)
372{
373    ScrnInfoPtr pScrn;
374
375    pScrn = xf86ScreenToScrn(pScreen);
376    *red = pScrn->gamma.red;
377    *green = pScrn->gamma.green;
378    *blue = pScrn->gamma.blue;
379    return TRUE;
380}
381
382static Bool
383xf86VidModeSetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
384{
385    xf86ChangeGammaRamp(pScreen, size, r, g, b);
386    return TRUE;
387}
388
389static Bool
390xf86VidModeGetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
391{
392    xf86GetGammaRamp(pScreen, size, r, g, b);
393    return TRUE;
394}
395
396static Bool
397xf86VidModeInit(ScreenPtr pScreen)
398{
399    VidModePtr pVidMode;
400
401    if (!xf86GetVidModeEnabled()) {
402        DebugF("!xf86GetVidModeEnabled()\n");
403        return FALSE;
404    }
405
406    pVidMode = VidModeInit(pScreen);
407    if (!pVidMode)
408        return FALSE;
409
410    pVidMode->Flags = 0;
411    pVidMode->Next = NULL;
412
413    pVidMode->GetMonitorValue = xf86VidModeGetMonitorValue;
414    pVidMode->GetCurrentModeline = xf86VidModeGetCurrentModeline;
415    pVidMode->GetFirstModeline = xf86VidModeGetFirstModeline;
416    pVidMode->GetNextModeline = xf86VidModeGetNextModeline;
417    pVidMode->DeleteModeline = xf86VidModeDeleteModeline;
418    pVidMode->ZoomViewport = xf86VidModeZoomViewport;
419    pVidMode->GetViewPort = xf86VidModeGetViewPort;
420    pVidMode->SetViewPort = xf86VidModeSetViewPort;
421    pVidMode->SwitchMode = xf86VidModeSwitchMode;
422    pVidMode->LockZoom = xf86VidModeLockZoom;
423    pVidMode->GetNumOfClocks = xf86VidModeGetNumOfClocks;
424    pVidMode->GetClocks = xf86VidModeGetClocks;
425    pVidMode->CheckModeForMonitor = xf86VidModeCheckModeForMonitor;
426    pVidMode->CheckModeForDriver = xf86VidModeCheckModeForDriver;
427    pVidMode->SetCrtcForMode = xf86VidModeSetCrtcForMode;
428    pVidMode->AddModeline = xf86VidModeAddModeline;
429    pVidMode->GetDotClock = xf86VidModeGetDotClock;
430    pVidMode->GetNumOfModes = xf86VidModeGetNumOfModes;
431    pVidMode->SetGamma = xf86VidModeSetGamma;
432    pVidMode->GetGamma = xf86VidModeGetGamma;
433    pVidMode->SetGammaRamp = xf86VidModeSetGammaRamp;
434    pVidMode->GetGammaRamp = xf86VidModeGetGammaRamp;
435    pVidMode->GetGammaRampSize = xf86GetGammaRampSize; /* use xf86cmap API directly */
436
437    return TRUE;
438}
439
440void
441XFree86VidModeExtensionInit(void)
442{
443    int i;
444    Bool enabled = FALSE;
445
446    DebugF("XFree86VidModeExtensionInit");
447
448    /* This means that the DDX doesn't want the vidmode extension enabled */
449    if (!xf86GetVidModeEnabled())
450        return;
451
452    for (i = 0; i < screenInfo.numScreens; i++) {
453        if (xf86VidModeInit (screenInfo.screens[i]))
454            enabled = TRUE;
455    }
456    /* This means that the DDX doesn't want the vidmode extension enabled */
457    if (!enabled)
458        return;
459
460   VidModeAddExtension(xf86GetVidModeAllowNonLocal());
461}
462
463#endif                          /* XF86VIDMODE */
464