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>
35 #include "mipointer.h"
38 typedef struct _xf86RandRInfo
{
39 CreateScreenResourcesProcPtr CreateScreenResources
;
40 CloseScreenProcPtr CloseScreen
;
46 } XF86RandRInfoRec
, *XF86RandRInfoPtr
;
48 static int xf86RandRIndex
= -1;
49 static int xf86RandRGeneration
;
51 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[xf86RandRIndex].ptr)
54 xf86RandRModeRefresh (DisplayModePtr mode
)
57 return (int) (mode
->VRefresh
+ 0.5);
59 return (int) (mode
->Clock
* 1000.0 / mode
->HTotal
/ mode
->VTotal
+ 0.5);
63 xf86RandRGetInfo (ScreenPtr pScreen
, Rotation
*rotations
)
65 RRScreenSizePtr pSize
;
66 ScrnInfoPtr scrp
= XF86SCRNINFO(pScreen
);
67 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
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
)
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
);
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
)
103 if (scrp
->currentMode
->HDisplay
!= randrp
->virtualX
||
104 scrp
->currentMode
->VDisplay
!= randrp
->virtualY
)
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
);
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
))
138 *rotations
= RRRotation
.RRRotations
;
145 xf86RandRSetMode (ScreenPtr pScreen
,
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
];
163 (*scrp
->EnableDisableFBAccess
) (pScreen
->myNum
, FALSE
);
166 scrp
->virtualX
= randrp
->virtualX
;
167 scrp
->virtualY
= randrp
->virtualY
;
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
;
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
;
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);
210 (*scrp
->EnableDisableFBAccess
) (pScreen
->myNum
, TRUE
);
215 xf86RandRSetConfig (ScreenPtr pScreen
,
218 RRScreenSizePtr pSize
)
220 ScrnInfoPtr scrp
= XF86SCRNINFO(pScreen
);
221 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
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
))
234 if (mode
->next
== scrp
->modes
)
236 if (pSize
->width
== randrp
->virtualX
&&
237 pSize
->height
== randrp
->virtualY
)
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
))
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
;
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
);
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
306 xf86RandRCreateScreenResources (ScreenPtr pScreen
)
308 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
310 ScrnInfoPtr scrp
= XF86SCRNINFO(pScreen
);
314 pScreen
->CreateScreenResources
= randrp
->CreateScreenResources
;
315 if (!(*pScreen
->CreateScreenResources
) (pScreen
))
319 mode
= scrp
->currentMode
;
321 xf86RandRSetMode (pScreen
, mode
, TRUE
);
328 * Reset size back to original
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
;
341 pScreen
->devPrivates
[xf86RandRIndex
].ptr
= 0;
342 return (*pScreen
->CloseScreen
) (index
, pScreen
);
346 xf86GetRotation(ScreenPtr pScreen
)
348 if (xf86RandRIndex
== -1)
351 return XF86RANDRINFO(pScreen
)->rotation
;
354 /* Function to change RandR's idea of the virtual screen size */
356 xf86RandRSetNewVirtualAndDimensions(ScreenPtr pScreen
,
357 int newvirtX
, int newvirtY
, int newmmWidth
, int newmmHeight
,
360 XF86RandRInfoPtr randrp
;
362 if (xf86RandRIndex
== -1)
365 randrp
= XF86RANDRINFO(pScreen
);
370 randrp
->virtualX
= newvirtX
;
373 randrp
->virtualY
= newvirtY
;
376 randrp
->mmWidth
= newmmWidth
;
379 randrp
->mmHeight
= newmmHeight
;
381 /* This is only for during server start */
383 return (xf86RandRSetMode(pScreen
,
384 XF86SCRNINFO(pScreen
)->currentMode
,
386 pScreen
->mmWidth
, pScreen
->mmHeight
));
393 xf86RandRInit (ScreenPtr pScreen
)
396 XF86RandRInfoPtr randrp
;
397 ScrnInfoPtr scrp
= XF86SCRNINFO(pScreen
);
400 /* XXX disable RandR when using Xinerama */
401 if (!noPanoramiXExtension
)
404 if (xf86RandRGeneration
!= serverGeneration
)
406 xf86RandRIndex
= AllocateScreenPrivateIndex();
407 xf86RandRGeneration
= serverGeneration
;
410 randrp
= xalloc (sizeof (XF86RandRInfoRec
));
414 if (!RRScreenInit (pScreen
))
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
;