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 #ifdef HAVE_DIX_CONFIG_H
29 #include <dix-config.h>
30 #endif
31 
32 #include <X11/X.h>
33 #include "misc.h"
34 #include "os.h"
35 #include "extinit.h"
36 
37 #ifdef XF86VIDMODE
38 #include "xwayland.h"
39 #include "randrstr.h"
40 #include "vidmodestr.h"
41 
42 static DevPrivateKeyRec xwlVidModePrivateKeyRec;
43 #define xwlVidModePrivateKey (&xwlVidModePrivateKeyRec)
44 
45 /* Taken from xrandr, h sync frequency in KHz */
46 static double
mode_hsync(const xRRModeInfo * mode_info)47 mode_hsync(const xRRModeInfo *mode_info)
48 {
49     double rate;
50 
51     if (mode_info->hTotal)
52         rate = (double) mode_info->dotClock / (double) mode_info->hTotal;
53     else
54         rate = 0.0;
55 
56     return rate / 1000.0;
57 }
58 
59 /* Taken from xrandr, v refresh frequency in Hz */
60 static double
mode_refresh(const xRRModeInfo * mode_info)61 mode_refresh(const xRRModeInfo *mode_info)
62 {
63     double rate;
64     double vTotal = mode_info->vTotal;
65 
66     if (mode_info->modeFlags & RR_DoubleScan)
67 	vTotal *= 2.0;
68 
69     if (mode_info->modeFlags & RR_Interlace)
70 	vTotal /= 2.0;
71 
72     if (mode_info->hTotal > 0.0 && vTotal > 0.0)
73 	rate = ((double) mode_info->dotClock /
74 		((double) mode_info->hTotal * (double) vTotal));
75     else
76         rate = 0.0;
77 
78     return rate;
79 }
80 
81 static Bool
xwlVidModeGetCurrentModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)82 xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
83 {
84     DisplayModePtr pMod;
85     RROutputPtr output;
86     RRCrtcPtr crtc;
87     xRRModeInfo rrmode;
88 
89     pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
90     if (pMod == NULL)
91         return FALSE;
92 
93     output = RRFirstOutput(pScreen);
94     if (output == NULL)
95         return FALSE;
96 
97     crtc = output->crtc;
98     if (crtc == NULL)
99         return FALSE;
100 
101     rrmode = crtc->mode->mode;
102 
103     pMod->next = pMod;
104     pMod->prev = pMod;
105     pMod->name = "";
106     pMod->VScan = 1;
107     pMod->Private = NULL;
108     pMod->HDisplay = rrmode.width;
109     pMod->HSyncStart = rrmode.hSyncStart;
110     pMod->HSyncEnd = rrmode.hSyncEnd;
111     pMod->HTotal = rrmode.hTotal;
112     pMod->HSkew = rrmode.hSkew;
113     pMod->VDisplay = rrmode.height;
114     pMod->VSyncStart = rrmode.vSyncStart;
115     pMod->VSyncEnd = rrmode.vSyncEnd;
116     pMod->VTotal = rrmode.vTotal;
117     pMod->Flags = rrmode.modeFlags;
118     pMod->Clock = rrmode.dotClock / 1000.0;
119     pMod->VRefresh = mode_refresh(&rrmode); /* Or RRVerticalRefresh() */
120     pMod->HSync = mode_hsync(&rrmode);
121     *mode = pMod;
122 
123     if (dotClock != NULL)
124         *dotClock = rrmode.dotClock / 1000.0;
125 
126     return TRUE;
127 }
128 
129 static vidMonitorValue
xwlVidModeGetMonitorValue(ScreenPtr pScreen,int valtyp,int indx)130 xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
131 {
132     vidMonitorValue ret = { NULL, };
133     DisplayModePtr pMod;
134 
135     if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
136         return ret;
137 
138     switch (valtyp) {
139     case VIDMODE_MON_VENDOR:
140         ret.ptr = XVENDORNAME;
141         break;
142     case VIDMODE_MON_MODEL:
143         ret.ptr = "XWAYLAND";
144         break;
145     case VIDMODE_MON_NHSYNC:
146         ret.i = 1;
147         break;
148     case VIDMODE_MON_NVREFRESH:
149         ret.i = 1;
150         break;
151     case VIDMODE_MON_HSYNC_LO:
152     case VIDMODE_MON_HSYNC_HI:
153         ret.f = 100.0 * pMod->HSync;
154         break;
155     case VIDMODE_MON_VREFRESH_LO:
156     case VIDMODE_MON_VREFRESH_HI:
157         ret.f = 100.0 * pMod->VRefresh;
158         break;
159     }
160     return ret;
161 }
162 
163 static int
xwlVidModeGetDotClock(ScreenPtr pScreen,int Clock)164 xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock)
165 {
166     DisplayModePtr pMod;
167 
168     if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
169         return 0;
170 
171     return pMod->Clock;
172 
173 }
174 
175 static int
xwlVidModeGetNumOfClocks(ScreenPtr pScreen,Bool * progClock)176 xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock)
177 {
178     return 1;
179 }
180 
181 static Bool
xwlVidModeGetClocks(ScreenPtr pScreen,int * Clocks)182 xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks)
183 {
184     *Clocks = xwlVidModeGetDotClock(pScreen, 0);
185 
186     return TRUE;
187 }
188 
189 static Bool
xwlVidModeGetNextModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)190 xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
191 {
192     return FALSE;
193 }
194 
195 static Bool
xwlVidModeGetFirstModeline(ScreenPtr pScreen,DisplayModePtr * mode,int * dotClock)196 xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
197 {
198     return xwlVidModeGetCurrentModeline(pScreen, mode, dotClock);
199 }
200 
201 static Bool
xwlVidModeDeleteModeline(ScreenPtr pScreen,DisplayModePtr mode)202 xwlVidModeDeleteModeline(ScreenPtr pScreen, DisplayModePtr mode)
203 {
204     /* Unsupported */
205     return FALSE;
206 }
207 
208 static Bool
xwlVidModeZoomViewport(ScreenPtr pScreen,int zoom)209 xwlVidModeZoomViewport(ScreenPtr pScreen, int zoom)
210 {
211     /* Support only no zoom */
212     return (zoom == 1);
213 }
214 
215 static Bool
xwlVidModeSetViewPort(ScreenPtr pScreen,int x,int y)216 xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y)
217 {
218     RROutputPtr output;
219     RRCrtcPtr crtc;
220 
221     output = RRFirstOutput(pScreen);
222     if (output == NULL)
223         return FALSE;
224 
225     crtc = output->crtc;
226     if (crtc == NULL)
227         return FALSE;
228 
229     /* Support only default viewport */
230     return (x == crtc->x && y == crtc->y);
231 }
232 
233 static Bool
xwlVidModeGetViewPort(ScreenPtr pScreen,int * x,int * y)234 xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
235 {
236     RROutputPtr output;
237     RRCrtcPtr crtc;
238 
239     output = RRFirstOutput(pScreen);
240     if (output == NULL)
241         return FALSE;
242 
243     crtc = output->crtc;
244     if (crtc == NULL)
245         return FALSE;
246 
247     *x = crtc->x;
248     *y = crtc->y;
249 
250     return TRUE;
251 }
252 
253 static Bool
xwlVidModeSwitchMode(ScreenPtr pScreen,DisplayModePtr mode)254 xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
255 {
256     /* Unsupported for now */
257     return FALSE;
258 }
259 
260 static Bool
xwlVidModeLockZoom(ScreenPtr pScreen,Bool lock)261 xwlVidModeLockZoom(ScreenPtr pScreen, Bool lock)
262 {
263     /* Unsupported for now, but pretend it works */
264     return TRUE;
265 }
266 
267 static ModeStatus
xwlVidModeCheckModeForMonitor(ScreenPtr pScreen,DisplayModePtr mode)268 xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
269 {
270     DisplayModePtr pMod;
271 
272     /* This should not happen */
273     if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
274         return MODE_ERROR;
275 
276     /* Only support mode with the same HSync/VRefresh as we advertise */
277     if (mode->HSync == pMod->HSync && mode->VRefresh == pMod->VRefresh)
278         return MODE_OK;
279 
280     /* All the rest is unsupported - If we want to succeed, return MODE_OK instead */
281     return MODE_ONE_SIZE;
282 }
283 
284 static ModeStatus
xwlVidModeCheckModeForDriver(ScreenPtr pScreen,DisplayModePtr mode)285 xwlVidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode)
286 {
287     DisplayModePtr pMod;
288 
289     /* This should not happen */
290     if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
291         return MODE_ERROR;
292 
293     if (mode->HTotal != pMod->HTotal)
294         return MODE_BAD_HVALUE;
295 
296     if (mode->VTotal != pMod->VTotal)
297         return MODE_BAD_VVALUE;
298 
299     /* Unsupported for now, but pretend it works */
300     return MODE_OK;
301 }
302 
303 static void
xwlVidModeSetCrtcForMode(ScreenPtr pScreen,DisplayModePtr mode)304 xwlVidModeSetCrtcForMode(ScreenPtr pScreen, DisplayModePtr mode)
305 {
306     /* Unsupported */
307     return;
308 }
309 
310 static Bool
xwlVidModeAddModeline(ScreenPtr pScreen,DisplayModePtr mode)311 xwlVidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode)
312 {
313     /* Unsupported */
314     return FALSE;
315 }
316 
317 static int
xwlVidModeGetNumOfModes(ScreenPtr pScreen)318 xwlVidModeGetNumOfModes(ScreenPtr pScreen)
319 {
320     /* We have only one mode */
321     return 1;
322 }
323 
324 static Bool
xwlVidModeSetGamma(ScreenPtr pScreen,float red,float green,float blue)325 xwlVidModeSetGamma(ScreenPtr pScreen, float red, float green, float blue)
326 {
327     /* Unsupported for now, but pretend it works */
328     return TRUE;
329 }
330 
331 static Bool
xwlVidModeGetGamma(ScreenPtr pScreen,float * red,float * green,float * blue)332 xwlVidModeGetGamma(ScreenPtr pScreen, float *red, float *green, float *blue)
333 {
334     /* Unsupported for now, but pretend it works */
335     *red = *green = *blue = 1.0f;
336     return TRUE;
337 }
338 
339 static Bool
xwlVidModeSetGammaRamp(ScreenPtr pScreen,int size,CARD16 * r,CARD16 * g,CARD16 * b)340 xwlVidModeSetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
341 {
342     /* Unsupported for now */
343     return FALSE;
344 }
345 
346 static Bool
xwlVidModeGetGammaRamp(ScreenPtr pScreen,int size,CARD16 * r,CARD16 * g,CARD16 * b)347 xwlVidModeGetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
348 {
349     /* Unsupported for now */
350     return FALSE;
351 }
352 
353 static int
xwlVidModeGetGammaRampSize(ScreenPtr pScreen)354 xwlVidModeGetGammaRampSize(ScreenPtr pScreen)
355 {
356     /* Unsupported for now */
357     return 0;
358 }
359 
360 static Bool
xwlVidModeInit(ScreenPtr pScreen)361 xwlVidModeInit(ScreenPtr pScreen)
362 {
363     VidModePtr pVidMode = NULL;
364 
365     pVidMode = VidModeInit(pScreen);
366     if (!pVidMode)
367         return FALSE;
368 
369     pVidMode->Flags = 0;
370     pVidMode->Next = NULL;
371 
372     pVidMode->GetMonitorValue = xwlVidModeGetMonitorValue;
373     pVidMode->GetCurrentModeline = xwlVidModeGetCurrentModeline;
374     pVidMode->GetFirstModeline = xwlVidModeGetFirstModeline;
375     pVidMode->GetNextModeline = xwlVidModeGetNextModeline;
376     pVidMode->DeleteModeline = xwlVidModeDeleteModeline;
377     pVidMode->ZoomViewport = xwlVidModeZoomViewport;
378     pVidMode->GetViewPort = xwlVidModeGetViewPort;
379     pVidMode->SetViewPort = xwlVidModeSetViewPort;
380     pVidMode->SwitchMode = xwlVidModeSwitchMode;
381     pVidMode->LockZoom = xwlVidModeLockZoom;
382     pVidMode->GetNumOfClocks = xwlVidModeGetNumOfClocks;
383     pVidMode->GetClocks = xwlVidModeGetClocks;
384     pVidMode->CheckModeForMonitor = xwlVidModeCheckModeForMonitor;
385     pVidMode->CheckModeForDriver = xwlVidModeCheckModeForDriver;
386     pVidMode->SetCrtcForMode = xwlVidModeSetCrtcForMode;
387     pVidMode->AddModeline = xwlVidModeAddModeline;
388     pVidMode->GetDotClock = xwlVidModeGetDotClock;
389     pVidMode->GetNumOfModes = xwlVidModeGetNumOfModes;
390     pVidMode->SetGamma = xwlVidModeSetGamma;
391     pVidMode->GetGamma = xwlVidModeGetGamma;
392     pVidMode->SetGammaRamp = xwlVidModeSetGammaRamp;
393     pVidMode->GetGammaRamp = xwlVidModeGetGammaRamp;
394     pVidMode->GetGammaRampSize = xwlVidModeGetGammaRampSize;
395 
396     return TRUE;
397 }
398 
399 void
xwlVidModeExtensionInit(void)400 xwlVidModeExtensionInit(void)
401 {
402     int i;
403     Bool enabled = FALSE;
404 
405     for (i = 0; i < screenInfo.numScreens; i++) {
406         if (xwlVidModeInit (screenInfo.screens[i]))
407             enabled = TRUE;
408     }
409     /* This means that the DDX doesn't want the vidmode extension enabled */
410     if (!enabled)
411         return;
412 
413     if (!dixRegisterPrivateKey(xwlVidModePrivateKey, PRIVATE_SCREEN,
414                                sizeof(DisplayModeRec)))
415         return;
416 
417     VidModeAddExtension(FALSE);
418 }
419 
420 #endif                          /* XF86VIDMODE */
421