Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / common / xf86RandR.c
blob288d72193d3271da6207caf38967ff2441abf2bf
1 /*
3 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
24 #ifdef HAVE_XORG_CONFIG_H
25 #include <xorg-config.h>
26 #endif
28 #include <X11/X.h>
29 #include "os.h"
30 #include "mibank.h"
31 #include "globals.h"
32 #include "xf86.h"
33 #include "xf86Priv.h"
34 #include "xf86DDC.h"
35 #include "mipointer.h"
36 #include <randrstr.h>
38 typedef struct _xf86RandRInfo {
39 CreateScreenResourcesProcPtr CreateScreenResources;
40 CloseScreenProcPtr CloseScreen;
41 int virtualX;
42 int virtualY;
43 int mmWidth;
44 int mmHeight;
45 Rotation rotation;
46 } XF86RandRInfoRec, *XF86RandRInfoPtr;
48 static int xf86RandRIndex = -1;
49 static int xf86RandRGeneration;
51 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[xf86RandRIndex].ptr)
53 static int
54 xf86RandRModeRefresh (DisplayModePtr mode)
56 if (mode->VRefresh)
57 return (int) (mode->VRefresh + 0.5);
58 else
59 return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
62 static Bool
63 xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
65 RRScreenSizePtr pSize;
66 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
67 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
68 DisplayModePtr mode;
69 int refresh0 = 60;
70 xorgRRModeMM RRModeMM;
72 *rotations = RR_Rotate_0;
74 for (mode = scrp->modes; ; mode = mode->next)
76 int refresh = xf86RandRModeRefresh (mode);
78 if (mode == scrp->modes)
79 refresh0 = refresh;
81 RRModeMM.mode = mode;
82 RRModeMM.virtX = randrp->virtualX;
83 RRModeMM.virtY = randrp->virtualY;
84 RRModeMM.mmWidth = randrp->mmWidth;
85 RRModeMM.mmHeight = randrp->mmHeight;
87 if(scrp->DriverFunc) {
88 (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM);
91 pSize = RRRegisterSize (pScreen,
92 mode->HDisplay, mode->VDisplay,
93 RRModeMM.mmWidth, RRModeMM.mmHeight);
94 if (!pSize)
95 return FALSE;
96 RRRegisterRate (pScreen, pSize, refresh);
97 if (mode == scrp->currentMode &&
98 mode->HDisplay == scrp->virtualX && mode->VDisplay == scrp->virtualY)
99 RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
100 if (mode->next == scrp->modes)
101 break;
103 if (scrp->currentMode->HDisplay != randrp->virtualX ||
104 scrp->currentMode->VDisplay != randrp->virtualY)
106 mode = scrp->modes;
108 RRModeMM.mode = NULL;
109 RRModeMM.virtX = randrp->virtualX;
110 RRModeMM.virtY = randrp->virtualY;
111 RRModeMM.mmWidth = randrp->mmWidth;
112 RRModeMM.mmHeight = randrp->mmHeight;
114 if(scrp->DriverFunc) {
115 (*scrp->DriverFunc)(scrp, RR_GET_MODE_MM, &RRModeMM);
118 pSize = RRRegisterSize (pScreen,
119 randrp->virtualX, randrp->virtualY,
120 RRModeMM.mmWidth, RRModeMM.mmHeight);
121 if (!pSize)
122 return FALSE;
123 RRRegisterRate (pScreen, pSize, refresh0);
124 if (scrp->virtualX == randrp->virtualX &&
125 scrp->virtualY == randrp->virtualY)
127 RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
131 /* If there is driver support for randr, let it set our supported rotations */
132 if(scrp->DriverFunc) {
133 xorgRRRotation RRRotation;
135 RRRotation.RRRotations = *rotations;
136 if (!(*scrp->DriverFunc)(scrp, RR_GET_INFO, &RRRotation))
137 return TRUE;
138 *rotations = RRRotation.RRRotations;
141 return TRUE;
144 static Bool
145 xf86RandRSetMode (ScreenPtr pScreen,
146 DisplayModePtr mode,
147 Bool useVirtual,
148 int mmWidth,
149 int mmHeight)
151 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
152 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
153 int oldWidth = pScreen->width;
154 int oldHeight = pScreen->height;
155 int oldmmWidth = pScreen->mmWidth;
156 int oldmmHeight = pScreen->mmHeight;
157 int oldVirtualX = scrp->virtualX;
158 int oldVirtualY = scrp->virtualY;
159 WindowPtr pRoot = WindowTable[pScreen->myNum];
160 Bool ret = TRUE;
162 if (pRoot)
163 (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
164 if (useVirtual)
166 scrp->virtualX = randrp->virtualX;
167 scrp->virtualY = randrp->virtualY;
169 else
171 scrp->virtualX = mode->HDisplay;
172 scrp->virtualY = mode->VDisplay;
174 if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
176 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
177 pScreen->width = scrp->virtualY;
178 pScreen->height = scrp->virtualX;
179 pScreen->mmWidth = mmHeight;
180 pScreen->mmHeight = mmWidth;
182 else
184 pScreen->width = scrp->virtualX;
185 pScreen->height = scrp->virtualY;
186 pScreen->mmWidth = mmWidth;
187 pScreen->mmHeight = mmHeight;
189 if (!xf86SwitchMode (pScreen, mode))
191 pScreen->width = oldWidth;
192 pScreen->height = oldHeight;
193 pScreen->mmWidth = oldmmWidth;
194 pScreen->mmHeight = oldmmHeight;
195 scrp->virtualX = oldVirtualX;
196 scrp->virtualY = oldVirtualY;
197 ret = FALSE;
200 * Make sure the layout is correct
202 xf86ReconfigureLayout();
205 * Make sure the whole screen is visible
207 xf86SetViewport (pScreen, pScreen->width, pScreen->height);
208 xf86SetViewport (pScreen, 0, 0);
209 if (pRoot)
210 (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
211 return ret;
214 static Bool
215 xf86RandRSetConfig (ScreenPtr pScreen,
216 Rotation rotation,
217 int rate,
218 RRScreenSizePtr pSize)
220 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
221 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
222 DisplayModePtr mode;
223 int px, py;
224 Bool useVirtual = FALSE;
225 Rotation oldRotation = randrp->rotation;
227 miPointerPosition (&px, &py);
228 for (mode = scrp->modes; ; mode = mode->next)
230 if (mode->HDisplay == pSize->width &&
231 mode->VDisplay == pSize->height &&
232 (rate == 0 || xf86RandRModeRefresh (mode) == rate))
233 break;
234 if (mode->next == scrp->modes)
236 if (pSize->width == randrp->virtualX &&
237 pSize->height == randrp->virtualY)
239 mode = scrp->modes;
240 useVirtual = TRUE;
241 break;
243 return FALSE;
247 if (randrp->rotation != rotation) {
249 /* Have the driver do its thing. */
250 if (scrp->DriverFunc) {
251 xorgRRRotation RRRotation;
252 RRRotation.RRConfig.rotation = rotation;
253 RRRotation.RRConfig.rate = rate;
254 RRRotation.RRConfig.width = pSize->width;
255 RRRotation.RRConfig.height = pSize->height;
258 * Currently we need to rely on HW support for rotation.
260 if (!(*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation))
261 return FALSE;
262 } else
263 return FALSE;
265 randrp->rotation = rotation;
268 if (!xf86RandRSetMode (pScreen, mode, useVirtual, pSize->mmWidth, pSize->mmHeight)) {
269 if(randrp->rotation != oldRotation) {
270 /* Have the driver undo its thing. */
271 if (scrp->DriverFunc) {
272 xorgRRRotation RRRotation;
273 RRRotation.RRConfig.rotation = oldRotation;
274 RRRotation.RRConfig.rate = xf86RandRModeRefresh (scrp->currentMode);
275 RRRotation.RRConfig.width = scrp->virtualX;
276 RRRotation.RRConfig.height = scrp->virtualY;
277 (*scrp->DriverFunc)(scrp, RR_SET_CONFIG, &RRRotation);
280 randrp->rotation = oldRotation;
282 return FALSE;
285 * Move the cursor back where it belongs; SwitchMode repositions it
287 if (pScreen == miPointerCurrentScreen ())
289 px = (px >= pScreen->width ? (pScreen->width - 1) : px);
290 py = (py >= pScreen->height ? (pScreen->height - 1) : py);
292 xf86SetViewport(pScreen, px, py);
294 (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
297 return TRUE;
301 * Wait until the screen is initialized before whacking the
302 * sizes around; otherwise the screen pixmap will be allocated
303 * at the current mode size rather than the maximum size
305 static Bool
306 xf86RandRCreateScreenResources (ScreenPtr pScreen)
308 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
309 #if 0
310 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
311 DisplayModePtr mode;
312 #endif
314 pScreen->CreateScreenResources = randrp->CreateScreenResources;
315 if (!(*pScreen->CreateScreenResources) (pScreen))
316 return FALSE;
318 #if 0
319 mode = scrp->currentMode;
320 if (mode)
321 xf86RandRSetMode (pScreen, mode, TRUE);
322 #endif
324 return TRUE;
328 * Reset size back to original
330 static Bool
331 xf86RandRCloseScreen (int index, ScreenPtr pScreen)
333 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
334 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
336 scrp->virtualX = pScreen->width = randrp->virtualX;
337 scrp->virtualY = pScreen->height = randrp->virtualY;
338 scrp->currentMode = scrp->modes;
339 pScreen->CloseScreen = randrp->CloseScreen;
340 xfree (randrp);
341 pScreen->devPrivates[xf86RandRIndex].ptr = 0;
342 return (*pScreen->CloseScreen) (index, pScreen);
345 _X_EXPORT Rotation
346 xf86GetRotation(ScreenPtr pScreen)
348 if (xf86RandRIndex == -1)
349 return RR_Rotate_0;
351 return XF86RANDRINFO(pScreen)->rotation;
354 /* Function to change RandR's idea of the virtual screen size */
355 _X_EXPORT Bool
356 xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen,
357 int newvirtX, int newvirtY, int newmmWidth, int newmmHeight,
358 Bool resetMode)
360 XF86RandRInfoPtr randrp;
362 if (xf86RandRIndex == -1)
363 return FALSE;
365 randrp = XF86RANDRINFO(pScreen);
366 if (randrp == NULL)
367 return FALSE;
369 if (newvirtX > 0)
370 randrp->virtualX = newvirtX;
372 if (newvirtY > 0)
373 randrp->virtualY = newvirtY;
375 if (newmmWidth > 0)
376 randrp->mmWidth = newmmWidth;
378 if (newmmHeight > 0)
379 randrp->mmHeight = newmmHeight;
381 /* This is only for during server start */
382 if (resetMode) {
383 return (xf86RandRSetMode(pScreen,
384 XF86SCRNINFO(pScreen)->currentMode,
385 TRUE,
386 pScreen->mmWidth, pScreen->mmHeight));
389 return TRUE;
392 Bool
393 xf86RandRInit (ScreenPtr pScreen)
395 rrScrPrivPtr rp;
396 XF86RandRInfoPtr randrp;
397 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
399 #ifdef PANORAMIX
400 /* XXX disable RandR when using Xinerama */
401 if (!noPanoramiXExtension)
402 return TRUE;
403 #endif
404 if (xf86RandRGeneration != serverGeneration)
406 xf86RandRIndex = AllocateScreenPrivateIndex();
407 xf86RandRGeneration = serverGeneration;
410 randrp = xalloc (sizeof (XF86RandRInfoRec));
411 if (!randrp)
412 return FALSE;
414 if (!RRScreenInit (pScreen))
416 xfree (randrp);
417 return FALSE;
419 rp = rrGetScrPriv(pScreen);
420 rp->rrGetInfo = xf86RandRGetInfo;
421 rp->rrSetConfig = xf86RandRSetConfig;
423 randrp->virtualX = scrp->virtualX;
424 randrp->virtualY = scrp->virtualY;
425 randrp->mmWidth = pScreen->mmWidth;
426 randrp->mmHeight = pScreen->mmHeight;
428 randrp->CreateScreenResources = pScreen->CreateScreenResources;
429 pScreen->CreateScreenResources = xf86RandRCreateScreenResources;
431 randrp->CloseScreen = pScreen->CloseScreen;
432 pScreen->CloseScreen = xf86RandRCloseScreen;
434 randrp->rotation = RR_Rotate_0;
436 pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
437 return TRUE;