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