2 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
34 #include "xf86Modes.h"
37 #include "mipointer.h"
38 #include "windowstr.h"
41 #include <X11/extensions/render.h>
44 #include "xf86RandR12.h"
46 typedef struct _xf86RandR12Info
{
55 Rotation rotation
; /* current mode */
56 Rotation supported_rotations
; /* driver supported */
58 /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends
59 * (actually, any time that we switch back into our VT).
61 * See https://bugs.freedesktop.org/show_bug.cgi?id=21554
63 xf86EnterVTProc
*orig_EnterVT
;
66 ConstrainCursorHarderProcPtr orig_ConstrainCursorHarder
;
67 } XF86RandRInfoRec
, *XF86RandRInfoPtr
;
69 #ifdef RANDR_12_INTERFACE
70 static Bool
xf86RandR12Init12(ScreenPtr pScreen
);
71 static Bool
xf86RandR12CreateScreenResources12(ScreenPtr pScreen
);
74 static int xf86RandR12Generation
;
76 static DevPrivateKeyRec xf86RandR12KeyRec
;
77 static DevPrivateKey xf86RandR12Key
;
79 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \
80 dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key))
83 xf86RandR12ModeRefresh(DisplayModePtr mode
)
86 return (int) (mode
->VRefresh
+ 0.5);
88 return (int) (mode
->Clock
* 1000.0 / mode
->HTotal
/ mode
->VTotal
+ 0.5);
91 /* Adapt panning area; return TRUE if panning area was valid without adaption */
93 xf86RandR13VerifyPanningArea(xf86CrtcPtr crtc
, int screenWidth
,
98 if (crtc
->version
< 2)
101 if (crtc
->panningTotalArea
.x2
<= crtc
->panningTotalArea
.x1
) {
102 /* Panning in X is disabled */
103 if (crtc
->panningTotalArea
.x1
|| crtc
->panningTotalArea
.x2
)
104 /* Illegal configuration -> fail/disable */
106 crtc
->panningTotalArea
.x1
= crtc
->panningTotalArea
.x2
= 0;
107 crtc
->panningTrackingArea
.x1
= crtc
->panningTrackingArea
.x2
= 0;
108 crtc
->panningBorder
[0] = crtc
->panningBorder
[2] = 0;
111 /* Panning in X is enabled */
112 if (crtc
->panningTotalArea
.x1
< 0) {
113 /* Panning region outside screen -> move inside */
114 crtc
->panningTotalArea
.x2
-= crtc
->panningTotalArea
.x1
;
115 crtc
->panningTotalArea
.x1
= 0;
118 if (crtc
->panningTotalArea
.x2
<
119 crtc
->panningTotalArea
.x1
+ crtc
->mode
.HDisplay
) {
120 /* Panning region smaller than displayed area -> crop to displayed area */
121 crtc
->panningTotalArea
.x2
=
122 crtc
->panningTotalArea
.x1
+ crtc
->mode
.HDisplay
;
125 if (crtc
->panningTotalArea
.x2
> screenWidth
) {
126 /* Panning region larger than screen -> move inside, then crop to screen */
127 crtc
->panningTotalArea
.x1
-=
128 crtc
->panningTotalArea
.x2
- screenWidth
;
129 crtc
->panningTotalArea
.x2
= screenWidth
;
131 if (crtc
->panningTotalArea
.x1
< 0)
132 crtc
->panningTotalArea
.x1
= 0;
134 if (crtc
->panningBorder
[0] + crtc
->panningBorder
[2] >
135 crtc
->mode
.HDisplay
) {
136 /* Borders too large -> set to 0 */
137 crtc
->panningBorder
[0] = crtc
->panningBorder
[2] = 0;
142 if (crtc
->panningTotalArea
.y2
<= crtc
->panningTotalArea
.y1
) {
143 /* Panning in Y is disabled */
144 if (crtc
->panningTotalArea
.y1
|| crtc
->panningTotalArea
.y2
)
145 /* Illegal configuration -> fail/disable */
147 crtc
->panningTotalArea
.y1
= crtc
->panningTotalArea
.y2
= 0;
148 crtc
->panningTrackingArea
.y1
= crtc
->panningTrackingArea
.y2
= 0;
149 crtc
->panningBorder
[1] = crtc
->panningBorder
[3] = 0;
152 /* Panning in Y is enabled */
153 if (crtc
->panningTotalArea
.y1
< 0) {
154 /* Panning region outside screen -> move inside */
155 crtc
->panningTotalArea
.y2
-= crtc
->panningTotalArea
.y1
;
156 crtc
->panningTotalArea
.y1
= 0;
159 if (crtc
->panningTotalArea
.y2
<
160 crtc
->panningTotalArea
.y1
+ crtc
->mode
.VDisplay
) {
161 /* Panning region smaller than displayed area -> crop to displayed area */
162 crtc
->panningTotalArea
.y2
=
163 crtc
->panningTotalArea
.y1
+ crtc
->mode
.VDisplay
;
166 if (crtc
->panningTotalArea
.y2
> screenHeight
) {
167 /* Panning region larger than screen -> move inside, then crop to screen */
168 crtc
->panningTotalArea
.y1
-=
169 crtc
->panningTotalArea
.y2
- screenHeight
;
170 crtc
->panningTotalArea
.y2
= screenHeight
;
172 if (crtc
->panningTotalArea
.y1
< 0)
173 crtc
->panningTotalArea
.y1
= 0;
175 if (crtc
->panningBorder
[1] + crtc
->panningBorder
[3] >
176 crtc
->mode
.VDisplay
) {
177 /* Borders too large -> set to 0 */
178 crtc
->panningBorder
[1] = crtc
->panningBorder
[3] = 0;
187 * The heart of the panning operation:
189 * Given a frame buffer position (fb_x, fb_y),
190 * and a crtc position (crtc_x, crtc_y),
191 * and a transform matrix which maps frame buffer to crtc,
192 * compute a panning position (pan_x, pan_y) that
193 * makes the resulting transform line those two up
197 xf86ComputeCrtcPan(Bool transform_in_use
,
198 struct pixman_f_transform
*m
,
199 double screen_x
, double screen_y
,
200 double crtc_x
, double crtc_y
,
201 int old_pan_x
, int old_pan_y
, int *new_pan_x
, int *new_pan_y
)
203 if (transform_in_use
) {
205 * Given the current transform, M, the current position
206 * on the Screen, S, and the desired position on the CRTC,
207 * C, compute a translation, T, such that:
211 * where T is of the form
218 * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F |
219 * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F |
220 * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F |
224 * Cx F = M00 dx + M01 dy + R0
225 * Cy F = M10 dx + M11 dy + R1
226 * F = M20 dx + M21 dy + R2
228 * Zero out dx, then dy
230 * F (Cx M10 - Cy M00) =
231 * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1
233 * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1
235 * F (Cx M11 - Cy M01) =
236 * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1
238 * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1
240 * Make some temporaries
242 * T = | Cx M10 - Cy M00 |
243 * | Cx M11 - Cy M01 |
245 * U = | M10 M01 - M00 M11 |
246 * | M11 M00 - M01 M10 |
248 * Q = | M10 R0 - M00 R1 |
249 * | M11 R0 - M01 R1 |
251 * P = | M10 - Cy M20 |
254 * W = | M10 M21 - M20 M11 |
255 * | M11 M20 - M21 M10 |
257 * V = | M10 R2 - M20 R1 |
258 * | M11 R2 - M21 R1 |
267 * Solve for F (two ways)
269 * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0
275 * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1
281 * We'll use which ever solution works (denominator != 0)
283 * Finally, solve for dx and dy:
285 * dx = (F T1 - Q1) / U1
286 * dx = (F P1 - V1) / W1
288 * dy = (F T0 - Q0) / U0
289 * dy = (F P0 - V0) / W0
292 double q
[2], u
[2], t
[2], v
[2], w
[2], p
[2];
294 struct pict_f_vector d
;
297 /* Get the un-normalized crtc coordinates again */
298 for (i
= 0; i
< 3; i
++)
299 r
[i
] = m
->m
[i
][0] * screen_x
+ m
->m
[i
][1] * screen_y
+ m
->m
[i
][2];
301 /* Combine values into temporaries */
302 for (i
= 0; i
< 2; i
++) {
303 q
[i
] = m
->m
[1][i
] * r
[0] - m
->m
[0][i
] * r
[1];
304 u
[i
] = m
->m
[1][i
] * m
->m
[0][1 - i
] - m
->m
[0][i
] * m
->m
[1][1 - i
];
305 t
[i
] = m
->m
[1][i
] * crtc_x
- m
->m
[0][i
] * crtc_y
;
307 v
[i
] = m
->m
[1][i
] * r
[2] - m
->m
[2][i
] * r
[1];
308 w
[i
] = m
->m
[1][i
] * m
->m
[2][1 - i
] - m
->m
[2][i
] * m
->m
[1][1 - i
];
309 p
[i
] = m
->m
[1][i
] - m
->m
[2][i
] * crtc_y
;
312 /* Find a way to compute f */
314 for (i
= 0; i
< 2; i
++) {
315 double a
= w
[i
] * q
[i
] - u
[i
] * v
[i
];
316 double b
= w
[i
] * t
[i
] - u
[i
] * p
[i
];
324 /* Solve for the resulting transform vector */
325 for (i
= 0; i
< 2; i
++) {
327 d
.v
[1 - i
] = (t
[i
] * f
- q
[i
]) / u
[i
];
329 d
.v
[1 - i
] = (p
[i
] * f
- v
[i
]) / w
[i
];
333 *new_pan_x
= old_pan_x
- floor(d
.v
[0] + 0.5);
334 *new_pan_y
= old_pan_y
- floor(d
.v
[1] + 0.5);
337 *new_pan_x
= screen_x
- crtc_x
;
338 *new_pan_y
= screen_y
- crtc_y
;
343 xf86RandR13Pan(xf86CrtcPtr crtc
, int x
, int y
)
349 if (crtc
->version
< 2)
352 if (!crtc
->enabled
||
353 (crtc
->panningTotalArea
.x2
<= crtc
->panningTotalArea
.x1
&&
354 crtc
->panningTotalArea
.y2
<= crtc
->panningTotalArea
.y1
))
359 width
= crtc
->mode
.HDisplay
;
360 height
= crtc
->mode
.VDisplay
;
362 if ((crtc
->panningTrackingArea
.x2
<= crtc
->panningTrackingArea
.x1
||
363 (x
>= crtc
->panningTrackingArea
.x1
&&
364 x
< crtc
->panningTrackingArea
.x2
)) &&
365 (crtc
->panningTrackingArea
.y2
<= crtc
->panningTrackingArea
.y1
||
366 (y
>= crtc
->panningTrackingArea
.y1
&&
367 y
< crtc
->panningTrackingArea
.y2
))) {
368 struct pict_f_vector c
;
371 * Pre-clip the mouse position to the panning area so that we don't
372 * push the crtc outside. This doesn't deal with changes to the
373 * panning values, only mouse position changes.
375 if (crtc
->panningTotalArea
.x2
> crtc
->panningTotalArea
.x1
) {
376 if (x
< crtc
->panningTotalArea
.x1
)
377 x
= crtc
->panningTotalArea
.x1
;
378 if (x
>= crtc
->panningTotalArea
.x2
)
379 x
= crtc
->panningTotalArea
.x2
- 1;
381 if (crtc
->panningTotalArea
.y2
> crtc
->panningTotalArea
.y1
) {
382 if (y
< crtc
->panningTotalArea
.y1
)
383 y
= crtc
->panningTotalArea
.y1
;
384 if (y
>= crtc
->panningTotalArea
.y2
)
385 y
= crtc
->panningTotalArea
.y2
- 1;
391 if (crtc
->transform_in_use
) {
392 pixman_f_transform_point(&crtc
->f_framebuffer_to_crtc
, &c
);
399 if (crtc
->panningTotalArea
.x2
> crtc
->panningTotalArea
.x1
) {
400 if (c
.v
[0] < crtc
->panningBorder
[0]) {
401 c
.v
[0] = crtc
->panningBorder
[0];
404 if (c
.v
[0] >= width
- crtc
->panningBorder
[2]) {
405 c
.v
[0] = width
- crtc
->panningBorder
[2] - 1;
409 if (crtc
->panningTotalArea
.y2
> crtc
->panningTotalArea
.y1
) {
410 if (c
.v
[1] < crtc
->panningBorder
[1]) {
411 c
.v
[1] = crtc
->panningBorder
[1];
414 if (c
.v
[1] >= height
- crtc
->panningBorder
[3]) {
415 c
.v
[1] = height
- crtc
->panningBorder
[3] - 1;
420 xf86ComputeCrtcPan(crtc
->transform_in_use
,
421 &crtc
->f_framebuffer_to_crtc
,
422 x
, y
, c
.v
[0], c
.v
[1], newX
, newY
, &newX
, &newY
);
426 * Ensure that the crtc is within the panning region.
428 * XXX This computation only works when we do not have a transform
431 if (!crtc
->transform_in_use
) {
432 /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
433 if (crtc
->panningTotalArea
.x2
> crtc
->panningTotalArea
.x1
) {
434 if (newX
> crtc
->panningTotalArea
.x2
- width
)
435 newX
= crtc
->panningTotalArea
.x2
- width
;
436 if (newX
< crtc
->panningTotalArea
.x1
)
437 newX
= crtc
->panningTotalArea
.x1
;
439 if (crtc
->panningTotalArea
.y2
> crtc
->panningTotalArea
.y1
) {
440 if (newY
> crtc
->panningTotalArea
.y2
- height
)
441 newY
= crtc
->panningTotalArea
.y2
- height
;
442 if (newY
< crtc
->panningTotalArea
.y1
)
443 newY
= crtc
->panningTotalArea
.y1
;
446 if (newX
!= crtc
->x
|| newY
!= crtc
->y
)
447 xf86CrtcSetOrigin(crtc
, newX
, newY
);
451 xf86RandR12GetInfo(ScreenPtr pScreen
, Rotation
* rotations
)
453 RRScreenSizePtr pSize
;
454 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
455 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
458 int maxX
= 0, maxY
= 0;
460 *rotations
= randrp
->supported_rotations
;
462 if (randrp
->virtualX
== -1 || randrp
->virtualY
== -1) {
463 randrp
->virtualX
= scrp
->virtualX
;
464 randrp
->virtualY
= scrp
->virtualY
;
467 /* Re-probe the outputs for new monitors or modes */
469 xf86ProbeOutputModes(scrp
, 0, 0);
470 xf86SetScrnInfoModes(scrp
);
473 for (mode
= scrp
->modes
;; mode
= mode
->next
) {
474 int refresh
= xf86RandR12ModeRefresh(mode
);
476 if (randrp
->maxX
== 0 || randrp
->maxY
== 0) {
477 if (maxX
< mode
->HDisplay
)
478 maxX
= mode
->HDisplay
;
479 if (maxY
< mode
->VDisplay
)
480 maxY
= mode
->VDisplay
;
482 if (mode
== scrp
->modes
)
484 pSize
= RRRegisterSize(pScreen
,
485 mode
->HDisplay
, mode
->VDisplay
,
486 randrp
->mmWidth
, randrp
->mmHeight
);
489 RRRegisterRate(pScreen
, pSize
, refresh
);
491 if (xf86ModesEqual(mode
, scrp
->currentMode
)) {
492 RRSetCurrentConfig(pScreen
, randrp
->rotation
, refresh
, pSize
);
494 if (mode
->next
== scrp
->modes
)
498 if (randrp
->maxX
== 0 || randrp
->maxY
== 0) {
507 xf86RandR12SetMode(ScreenPtr pScreen
,
509 Bool useVirtual
, int mmWidth
, int mmHeight
)
511 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
512 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
513 int oldWidth
= pScreen
->width
;
514 int oldHeight
= pScreen
->height
;
515 int oldmmWidth
= pScreen
->mmWidth
;
516 int oldmmHeight
= pScreen
->mmHeight
;
517 WindowPtr pRoot
= pScreen
->root
;
518 DisplayModePtr currentMode
= NULL
;
522 (*scrp
->EnableDisableFBAccess
) (scrp
, FALSE
);
524 scrp
->virtualX
= randrp
->virtualX
;
525 scrp
->virtualY
= randrp
->virtualY
;
528 scrp
->virtualX
= mode
->HDisplay
;
529 scrp
->virtualY
= mode
->VDisplay
;
532 if (randrp
->rotation
& (RR_Rotate_90
| RR_Rotate_270
)) {
533 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
534 pScreen
->width
= scrp
->virtualY
;
535 pScreen
->height
= scrp
->virtualX
;
536 pScreen
->mmWidth
= mmHeight
;
537 pScreen
->mmHeight
= mmWidth
;
540 pScreen
->width
= scrp
->virtualX
;
541 pScreen
->height
= scrp
->virtualY
;
542 pScreen
->mmWidth
= mmWidth
;
543 pScreen
->mmHeight
= mmHeight
;
545 if (scrp
->currentMode
== mode
) {
546 /* Save current mode */
547 currentMode
= scrp
->currentMode
;
548 /* Reset, just so we ensure the drivers SwitchMode is called */
549 scrp
->currentMode
= NULL
;
552 * We know that if the driver failed to SwitchMode to the rotated
553 * version, then it should revert back to it's prior mode.
555 if (!xf86SwitchMode(pScreen
, mode
)) {
557 scrp
->virtualX
= pScreen
->width
= oldWidth
;
558 scrp
->virtualY
= pScreen
->height
= oldHeight
;
559 pScreen
->mmWidth
= oldmmWidth
;
560 pScreen
->mmHeight
= oldmmHeight
;
561 scrp
->currentMode
= currentMode
;
565 * Make sure the layout is correct
567 xf86ReconfigureLayout();
570 * Make sure the whole screen is visible
572 xf86SetViewport(pScreen
, pScreen
->width
, pScreen
->height
);
573 xf86SetViewport(pScreen
, 0, 0);
575 (*scrp
->EnableDisableFBAccess
) (scrp
, TRUE
);
580 xf86RandR12SetConfig(ScreenPtr pScreen
,
581 Rotation rotation
, int rate
, RRScreenSizePtr pSize
)
583 ScrnInfoPtr scrp
= xf86ScreenToScrn(pScreen
);
584 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
586 int pos
[MAXDEVICES
][2];
587 Bool useVirtual
= FALSE
;
588 int maxX
= 0, maxY
= 0;
589 Rotation oldRotation
= randrp
->rotation
;
591 Bool view_adjusted
= FALSE
;
593 randrp
->rotation
= rotation
;
595 if (randrp
->virtualX
== -1 || randrp
->virtualY
== -1) {
596 randrp
->virtualX
= scrp
->virtualX
;
597 randrp
->virtualY
= scrp
->virtualY
;
600 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
601 if (!IsMaster(dev
) && !IsFloating(dev
))
604 miPointerGetPosition(dev
, &pos
[dev
->id
][0], &pos
[dev
->id
][1]);
607 for (mode
= scrp
->modes
;; mode
= mode
->next
) {
608 if (randrp
->maxX
== 0 || randrp
->maxY
== 0) {
609 if (maxX
< mode
->HDisplay
)
610 maxX
= mode
->HDisplay
;
611 if (maxY
< mode
->VDisplay
)
612 maxY
= mode
->VDisplay
;
614 if (mode
->HDisplay
== pSize
->width
&&
615 mode
->VDisplay
== pSize
->height
&&
616 (rate
== 0 || xf86RandR12ModeRefresh(mode
) == rate
))
618 if (mode
->next
== scrp
->modes
) {
619 if (pSize
->width
== randrp
->virtualX
&&
620 pSize
->height
== randrp
->virtualY
) {
625 if (randrp
->maxX
== 0 || randrp
->maxY
== 0) {
633 if (randrp
->maxX
== 0 || randrp
->maxY
== 0) {
638 if (!xf86RandR12SetMode(pScreen
, mode
, useVirtual
, pSize
->mmWidth
,
640 randrp
->rotation
= oldRotation
;
645 * Move the cursor back where it belongs; SwitchMode repositions it
646 * FIXME: duplicated code, see modes/xf86RandR12.c
648 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
649 if (!IsMaster(dev
) && !IsFloating(dev
))
652 if (pScreen
== miPointerGetScreen(dev
)) {
653 int px
= pos
[dev
->id
][0];
654 int py
= pos
[dev
->id
][1];
656 px
= (px
>= pScreen
->width
? (pScreen
->width
- 1) : px
);
657 py
= (py
>= pScreen
->height
? (pScreen
->height
- 1) : py
);
659 /* Setting the viewpoint makes only sense on one device */
660 if (!view_adjusted
&& IsMaster(dev
)) {
661 xf86SetViewport(pScreen
, px
, py
);
662 view_adjusted
= TRUE
;
665 (*pScreen
->SetCursorPosition
) (dev
, pScreen
, px
, py
, FALSE
);
672 #define PANNING_ENABLED(crtc) \
673 ((crtc)->panningTotalArea.x2 > (crtc)->panningTotalArea.x1 || \
674 (crtc)->panningTotalArea.y2 > (crtc)->panningTotalArea.y1)
677 xf86RandR12ScreenSetSize(ScreenPtr pScreen
,
679 CARD16 height
, CARD32 mmWidth
, CARD32 mmHeight
)
681 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
682 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
683 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
684 WindowPtr pRoot
= pScreen
->root
;
687 Bool panning
= FALSE
;
690 if (xf86RandR12Key
) {
691 if (randrp
->virtualX
== -1 || randrp
->virtualY
== -1) {
692 randrp
->virtualX
= pScrn
->virtualX
;
693 randrp
->virtualY
= pScrn
->virtualY
;
696 if (pRoot
&& pScrn
->vtSema
)
697 (*pScrn
->EnableDisableFBAccess
) (pScrn
, FALSE
);
699 /* Let the driver update virtualX and virtualY */
700 if (!(*config
->funcs
->resize
) (pScrn
, width
, height
))
704 /* Update panning information */
705 for (c
= 0; c
< config
->num_crtc
; c
++) {
706 xf86CrtcPtr crtc
= config
->crtc
[c
];
708 if (PANNING_ENABLED (crtc
)) {
709 if (crtc
->panningTotalArea
.x2
> crtc
->panningTrackingArea
.x1
)
710 crtc
->panningTotalArea
.x2
+= width
- pScreen
->width
;
711 if (crtc
->panningTotalArea
.y2
> crtc
->panningTrackingArea
.y1
)
712 crtc
->panningTotalArea
.y2
+= height
- pScreen
->height
;
713 if (crtc
->panningTrackingArea
.x2
> crtc
->panningTrackingArea
.x1
)
714 crtc
->panningTrackingArea
.x2
+= width
- pScreen
->width
;
715 if (crtc
->panningTrackingArea
.y2
> crtc
->panningTrackingArea
.y1
)
716 crtc
->panningTrackingArea
.y2
+= height
- pScreen
->height
;
717 xf86RandR13VerifyPanningArea(crtc
, width
, height
);
718 xf86RandR13Pan(crtc
, randrp
->pointerX
, randrp
->pointerY
);
723 pScrnPix
= (*pScreen
->GetScreenPixmap
) (pScreen
);
724 pScreen
->width
= pScrnPix
->drawable
.width
= width
;
725 pScreen
->height
= pScrnPix
->drawable
.height
= height
;
726 randrp
->mmWidth
= pScreen
->mmWidth
= mmWidth
;
727 randrp
->mmHeight
= pScreen
->mmHeight
= mmHeight
;
729 xf86SetViewport(pScreen
, pScreen
->width
- 1, pScreen
->height
- 1);
730 xf86SetViewport(pScreen
, 0, 0);
733 update_desktop_dimensions();
735 if (pRoot
&& pScrn
->vtSema
)
736 (*pScrn
->EnableDisableFBAccess
) (pScrn
, TRUE
);
737 #if RANDR_12_INTERFACE
738 if (xf86RandR12Key
&& pScreen
->root
&& ret
)
739 RRScreenSizeNotify(pScreen
);
745 xf86RandR12GetRotation(ScreenPtr pScreen
)
747 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
749 return randrp
->rotation
;
753 xf86RandR12CreateScreenResources(ScreenPtr pScreen
)
755 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
756 xf86CrtcConfigPtr config
;
757 XF86RandRInfoPtr randrp
;
760 int mmWidth
, mmHeight
;
763 /* XXX disable RandR when using Xinerama */
764 if (!noPanoramiXExtension
)
768 config
= XF86_CRTC_CONFIG_PTR(pScrn
);
769 randrp
= XF86RANDRINFO(pScreen
);
771 * Compute size of screen
775 for (c
= 0; c
< config
->num_crtc
; c
++) {
776 xf86CrtcPtr crtc
= config
->crtc
[c
];
777 int crtc_width
= crtc
->x
+ xf86ModeWidth(&crtc
->mode
, crtc
->rotation
);
778 int crtc_height
= crtc
->y
+ xf86ModeHeight(&crtc
->mode
, crtc
->rotation
);
781 if (crtc_width
> width
)
783 if (crtc_height
> height
)
784 height
= crtc_height
;
785 if (crtc
->panningTotalArea
.x2
> width
)
786 width
= crtc
->panningTotalArea
.x2
;
787 if (crtc
->panningTotalArea
.y2
> height
)
788 height
= crtc
->panningTotalArea
.y2
;
792 if (width
&& height
) {
794 * Compute physical size of screen
796 if (monitorResolution
) {
797 mmWidth
= width
* 25.4 / monitorResolution
;
798 mmHeight
= height
* 25.4 / monitorResolution
;
801 xf86OutputPtr output
= xf86CompatOutput(pScrn
);
804 output
->conf_monitor
&&
805 (output
->conf_monitor
->mon_width
> 0 &&
806 output
->conf_monitor
->mon_height
> 0)) {
808 * Prefer user configured DisplaySize
810 mmWidth
= output
->conf_monitor
->mon_width
;
811 mmHeight
= output
->conf_monitor
->mon_height
;
815 * Otherwise, just set the screen to DEFAULT_DPI
817 mmWidth
= width
* 25.4 / DEFAULT_DPI
;
818 mmHeight
= height
* 25.4 / DEFAULT_DPI
;
821 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
822 "Setting screen physical size to %d x %d\n",
825 * This is the initial setting of the screen size.
826 * We have to pre-set it here, otherwise panning would be adapted
827 * to the new screen size.
829 pScreen
->width
= width
;
830 pScreen
->height
= height
;
831 xf86RandR12ScreenSetSize(pScreen
, width
, height
, mmWidth
, mmHeight
);
834 if (xf86RandR12Key
== NULL
)
837 if (randrp
->virtualX
== -1 || randrp
->virtualY
== -1) {
838 randrp
->virtualX
= pScrn
->virtualX
;
839 randrp
->virtualY
= pScrn
->virtualY
;
841 xf86CrtcSetScreenSubpixelOrder(pScreen
);
842 #if RANDR_12_INTERFACE
843 if (xf86RandR12CreateScreenResources12(pScreen
))
850 xf86RandR12Init(ScreenPtr pScreen
)
853 XF86RandRInfoPtr randrp
;
856 /* XXX disable RandR when using Xinerama */
857 if (!noPanoramiXExtension
) {
858 if (xf86NumScreens
== 1)
859 noPanoramiXExtension
= TRUE
;
865 if (xf86RandR12Generation
!= serverGeneration
)
866 xf86RandR12Generation
= serverGeneration
;
868 xf86RandR12Key
= &xf86RandR12KeyRec
;
869 if (!dixRegisterPrivateKey(&xf86RandR12KeyRec
, PRIVATE_SCREEN
, 0))
872 randrp
= malloc(sizeof(XF86RandRInfoRec
));
876 if (!RRScreenInit(pScreen
)) {
880 rp
= rrGetScrPriv(pScreen
);
881 rp
->rrGetInfo
= xf86RandR12GetInfo
;
882 rp
->rrSetConfig
= xf86RandR12SetConfig
;
884 randrp
->virtualX
= -1;
885 randrp
->virtualY
= -1;
886 randrp
->mmWidth
= pScreen
->mmWidth
;
887 randrp
->mmHeight
= pScreen
->mmHeight
;
889 randrp
->rotation
= RR_Rotate_0
; /* initial rotated mode */
891 randrp
->supported_rotations
= RR_Rotate_0
;
893 randrp
->maxX
= randrp
->maxY
= 0;
895 dixSetPrivate(&pScreen
->devPrivates
, xf86RandR12Key
, randrp
);
897 #if RANDR_12_INTERFACE
898 if (!xf86RandR12Init12(pScreen
))
905 xf86RandR12CloseScreen(ScreenPtr pScreen
)
907 XF86RandRInfoPtr randrp
;
909 if (xf86RandR12Key
== NULL
)
912 randrp
= XF86RANDRINFO(pScreen
);
913 #if RANDR_12_INTERFACE
914 xf86ScreenToScrn(pScreen
)->EnterVT
= randrp
->orig_EnterVT
;
915 pScreen
->ConstrainCursorHarder
= randrp
->orig_ConstrainCursorHarder
;
922 xf86RandR12SetRotations(ScreenPtr pScreen
, Rotation rotations
)
924 XF86RandRInfoPtr randrp
;
926 #if RANDR_12_INTERFACE
927 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
929 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
932 if (xf86RandR12Key
== NULL
)
935 randrp
= XF86RANDRINFO(pScreen
);
936 #if RANDR_12_INTERFACE
937 for (c
= 0; c
< config
->num_crtc
; c
++) {
938 xf86CrtcPtr crtc
= config
->crtc
[c
];
940 RRCrtcSetRotations(crtc
->randr_crtc
, rotations
);
943 randrp
->supported_rotations
= rotations
;
947 xf86RandR12SetTransformSupport(ScreenPtr pScreen
, Bool transforms
)
949 XF86RandRInfoPtr randrp
;
951 #if RANDR_13_INTERFACE
952 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
954 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
957 if (xf86RandR12Key
== NULL
)
960 randrp
= XF86RANDRINFO(pScreen
);
961 #if RANDR_13_INTERFACE
962 for (c
= 0; c
< config
->num_crtc
; c
++) {
963 xf86CrtcPtr crtc
= config
->crtc
[c
];
965 RRCrtcSetTransformSupport(crtc
->randr_crtc
, transforms
);
971 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn
, int *x
, int *y
)
973 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
975 if (xf86RandR12Generation
!= serverGeneration
||
976 XF86RANDRINFO(pScreen
)->virtualX
== -1) {
977 *x
= pScrn
->virtualX
;
978 *y
= pScrn
->virtualY
;
981 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
983 *x
= randrp
->virtualX
;
984 *y
= randrp
->virtualY
;
988 #if RANDR_12_INTERFACE
990 #define FLAG_BITS (RR_HSyncPositive | \
1001 RR_PixelMultiplex | \
1006 xf86RandRModeMatches(RRModePtr randr_mode
, DisplayModePtr mode
)
1010 /* check for same name */
1011 int len
= strlen(mode
->name
);
1013 if (randr_mode
->mode
.nameLength
!= len
)
1015 if (memcmp(randr_mode
->name
, mode
->name
, len
) != 0)
1020 /* check for same timings */
1021 if (randr_mode
->mode
.dotClock
/ 1000 != mode
->Clock
)
1023 if (randr_mode
->mode
.width
!= mode
->HDisplay
)
1025 if (randr_mode
->mode
.hSyncStart
!= mode
->HSyncStart
)
1027 if (randr_mode
->mode
.hSyncEnd
!= mode
->HSyncEnd
)
1029 if (randr_mode
->mode
.hTotal
!= mode
->HTotal
)
1031 if (randr_mode
->mode
.hSkew
!= mode
->HSkew
)
1033 if (randr_mode
->mode
.height
!= mode
->VDisplay
)
1035 if (randr_mode
->mode
.vSyncStart
!= mode
->VSyncStart
)
1037 if (randr_mode
->mode
.vSyncEnd
!= mode
->VSyncEnd
)
1039 if (randr_mode
->mode
.vTotal
!= mode
->VTotal
)
1042 /* check for same flags (using only the XF86 valid flag bits) */
1043 if ((randr_mode
->mode
.modeFlags
& FLAG_BITS
) != (mode
->Flags
& FLAG_BITS
))
1046 /* everything matches */
1051 xf86RandR12CrtcNotify(RRCrtcPtr randr_crtc
)
1053 ScreenPtr pScreen
= randr_crtc
->pScreen
;
1054 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1055 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1056 RRModePtr randr_mode
= NULL
;
1061 RROutputPtr
*randr_outputs
;
1062 RROutputPtr randr_output
;
1063 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1064 xf86OutputPtr output
;
1066 DisplayModePtr mode
= &crtc
->mode
;
1069 randr_outputs
= malloc(config
->num_output
* sizeof(RROutputPtr
));
1074 rotation
= crtc
->rotation
;
1077 for (i
= 0; i
< config
->num_output
; i
++) {
1078 output
= config
->output
[i
];
1079 if (output
->crtc
== crtc
) {
1080 randr_output
= output
->randr_output
;
1081 randr_outputs
[numOutputs
++] = randr_output
;
1083 * We make copies of modes, so pointer equality
1086 for (j
= 0; j
< randr_output
->numModes
+ randr_output
->numUserModes
;
1090 randr_output
->numModes
? randr_output
->
1091 modes
[j
] : randr_output
->userModes
[j
-
1095 if (xf86RandRModeMatches(m
, mode
)) {
1102 ret
= RRCrtcNotify(randr_crtc
, randr_mode
, x
, y
,
1104 crtc
->transformPresent
? &crtc
->transform
: NULL
,
1105 numOutputs
, randr_outputs
);
1106 free(randr_outputs
);
1111 * Convert a RandR mode to a DisplayMode
1114 xf86RandRModeConvert(ScrnInfoPtr scrn
,
1115 RRModePtr randr_mode
, DisplayModePtr mode
)
1117 memset(mode
, 0, sizeof(DisplayModeRec
));
1118 mode
->status
= MODE_OK
;
1120 mode
->Clock
= randr_mode
->mode
.dotClock
/ 1000;
1122 mode
->HDisplay
= randr_mode
->mode
.width
;
1123 mode
->HSyncStart
= randr_mode
->mode
.hSyncStart
;
1124 mode
->HSyncEnd
= randr_mode
->mode
.hSyncEnd
;
1125 mode
->HTotal
= randr_mode
->mode
.hTotal
;
1126 mode
->HSkew
= randr_mode
->mode
.hSkew
;
1128 mode
->VDisplay
= randr_mode
->mode
.height
;
1129 mode
->VSyncStart
= randr_mode
->mode
.vSyncStart
;
1130 mode
->VSyncEnd
= randr_mode
->mode
.vSyncEnd
;
1131 mode
->VTotal
= randr_mode
->mode
.vTotal
;
1134 mode
->Flags
= randr_mode
->mode
.modeFlags
& FLAG_BITS
;
1136 xf86SetModeCrtc(mode
, scrn
->adjustFlags
);
1140 xf86RandR12CrtcSet(ScreenPtr pScreen
,
1141 RRCrtcPtr randr_crtc
,
1142 RRModePtr randr_mode
,
1146 int num_randr_outputs
, RROutputPtr
* randr_outputs
)
1148 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
1149 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1150 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1151 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1152 RRTransformPtr transform
;
1153 Bool changed
= FALSE
;
1155 xf86CrtcPtr
*save_crtcs
;
1156 Bool save_enabled
= crtc
->enabled
;
1158 if (!crtc
->scrn
->vtSema
)
1161 save_crtcs
= malloc(config
->num_output
* sizeof(xf86CrtcPtr
));
1162 if ((randr_mode
!= NULL
) != crtc
->enabled
)
1164 else if (randr_mode
&& !xf86RandRModeMatches(randr_mode
, &crtc
->mode
))
1167 if (rotation
!= crtc
->rotation
)
1170 if (crtc
->current_scanout
!= randr_crtc
->scanout_pixmap
)
1173 transform
= RRCrtcGetTransform(randr_crtc
);
1174 if ((transform
!= NULL
) != crtc
->transformPresent
)
1176 else if (transform
&&
1177 memcmp(&transform
->transform
, &crtc
->transform
.transform
,
1178 sizeof(transform
->transform
)) != 0)
1181 if (x
!= crtc
->x
|| y
!= crtc
->y
)
1183 for (o
= 0; o
< config
->num_output
; o
++) {
1184 xf86OutputPtr output
= config
->output
[o
];
1185 xf86CrtcPtr new_crtc
;
1187 save_crtcs
[o
] = output
->crtc
;
1189 if (output
->crtc
== crtc
)
1192 new_crtc
= output
->crtc
;
1193 for (ro
= 0; ro
< num_randr_outputs
; ro
++)
1194 if (output
->randr_output
== randr_outputs
[ro
]) {
1198 if (new_crtc
!= output
->crtc
) {
1200 output
->crtc
= new_crtc
;
1203 for (ro
= 0; ro
< num_randr_outputs
; ro
++)
1204 if (randr_outputs
[ro
]->pendingProperties
)
1207 /* XXX need device-independent mode setting code through an API */
1209 crtc
->enabled
= randr_mode
!= NULL
;
1212 DisplayModeRec mode
;
1213 RRTransformPtr transform
= RRCrtcGetTransform(randr_crtc
);
1215 xf86RandRModeConvert(pScrn
, randr_mode
, &mode
);
1216 if (!xf86CrtcSetModeTransform
1217 (crtc
, &mode
, rotation
, transform
, x
, y
)) {
1218 crtc
->enabled
= save_enabled
;
1219 for (o
= 0; o
< config
->num_output
; o
++) {
1220 xf86OutputPtr output
= config
->output
[o
];
1222 output
->crtc
= save_crtcs
[o
];
1227 xf86RandR13VerifyPanningArea(crtc
, pScreen
->width
, pScreen
->height
);
1228 xf86RandR13Pan(crtc
, randrp
->pointerX
, randrp
->pointerY
);
1229 randrp
->panning
= PANNING_ENABLED (crtc
);
1231 * Save the last successful setting for EnterVT
1233 xf86SaveModeContents(&crtc
->desiredMode
, &mode
);
1234 crtc
->desiredRotation
= rotation
;
1235 crtc
->current_scanout
= randr_crtc
->scanout_pixmap
;
1237 crtc
->desiredTransform
= *transform
;
1238 crtc
->desiredTransformPresent
= TRUE
;
1241 crtc
->desiredTransformPresent
= FALSE
;
1246 xf86DisableUnusedFunctions(pScrn
);
1249 return xf86RandR12CrtcNotify(randr_crtc
);
1253 xf86RandR12CrtcSetGamma(ScreenPtr pScreen
, RRCrtcPtr randr_crtc
)
1255 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1257 if (crtc
->funcs
->gamma_set
== NULL
)
1260 if (!crtc
->scrn
->vtSema
)
1263 /* Realloc local gamma if needed. */
1264 if (randr_crtc
->gammaSize
!= crtc
->gamma_size
) {
1268 realloc(crtc
->gamma_red
, 3 * crtc
->gamma_size
* sizeof(CARD16
));
1271 crtc
->gamma_red
= tmp_ptr
;
1272 crtc
->gamma_green
= crtc
->gamma_red
+ crtc
->gamma_size
;
1273 crtc
->gamma_blue
= crtc
->gamma_green
+ crtc
->gamma_size
;
1276 crtc
->gamma_size
= randr_crtc
->gammaSize
;
1277 memcpy(crtc
->gamma_red
, randr_crtc
->gammaRed
,
1278 crtc
->gamma_size
* sizeof(CARD16
));
1279 memcpy(crtc
->gamma_green
, randr_crtc
->gammaGreen
,
1280 crtc
->gamma_size
* sizeof(CARD16
));
1281 memcpy(crtc
->gamma_blue
, randr_crtc
->gammaBlue
,
1282 crtc
->gamma_size
* sizeof(CARD16
));
1284 /* Only set it when the crtc is actually running.
1285 * Otherwise it will be set when it's activated.
1288 crtc
->funcs
->gamma_set(crtc
, crtc
->gamma_red
, crtc
->gamma_green
,
1289 crtc
->gamma_blue
, crtc
->gamma_size
);
1295 xf86RandR12CrtcGetGamma(ScreenPtr pScreen
, RRCrtcPtr randr_crtc
)
1297 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1299 if (!crtc
->gamma_size
)
1302 if (!crtc
->gamma_red
|| !crtc
->gamma_green
|| !crtc
->gamma_blue
)
1305 /* Realloc randr gamma if needed. */
1306 if (randr_crtc
->gammaSize
!= crtc
->gamma_size
) {
1310 realloc(randr_crtc
->gammaRed
,
1311 3 * crtc
->gamma_size
* sizeof(CARD16
));
1314 randr_crtc
->gammaRed
= tmp_ptr
;
1315 randr_crtc
->gammaGreen
= randr_crtc
->gammaRed
+ crtc
->gamma_size
;
1316 randr_crtc
->gammaBlue
= randr_crtc
->gammaGreen
+ crtc
->gamma_size
;
1318 randr_crtc
->gammaSize
= crtc
->gamma_size
;
1319 memcpy(randr_crtc
->gammaRed
, crtc
->gamma_red
,
1320 crtc
->gamma_size
* sizeof(CARD16
));
1321 memcpy(randr_crtc
->gammaGreen
, crtc
->gamma_green
,
1322 crtc
->gamma_size
* sizeof(CARD16
));
1323 memcpy(randr_crtc
->gammaBlue
, crtc
->gamma_blue
,
1324 crtc
->gamma_size
* sizeof(CARD16
));
1330 xf86RandR12OutputSetProperty(ScreenPtr pScreen
,
1331 RROutputPtr randr_output
,
1332 Atom property
, RRPropertyValuePtr value
)
1334 xf86OutputPtr output
= randr_output
->devPrivate
;
1336 /* If we don't have any property handler, then we don't care what the
1337 * user is setting properties to.
1339 if (output
->funcs
->set_property
== NULL
)
1343 * This function gets called even when vtSema is FALSE, as
1344 * drivers will need to remember the correct value to apply
1345 * when the VT switch occurs
1347 return output
->funcs
->set_property(output
, property
, value
);
1351 xf86RandR13OutputGetProperty(ScreenPtr pScreen
,
1352 RROutputPtr randr_output
, Atom property
)
1354 xf86OutputPtr output
= randr_output
->devPrivate
;
1356 if (output
->funcs
->get_property
== NULL
)
1359 /* Should be safe even w/o vtSema */
1360 return output
->funcs
->get_property(output
, property
);
1364 xf86RandR12OutputValidateMode(ScreenPtr pScreen
,
1365 RROutputPtr randr_output
, RRModePtr randr_mode
)
1367 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1368 xf86OutputPtr output
= randr_output
->devPrivate
;
1369 DisplayModeRec mode
;
1371 xf86RandRModeConvert(pScrn
, randr_mode
, &mode
);
1373 * This function may be called when vtSema is FALSE, so
1374 * the underlying function must either avoid touching the hardware
1375 * or return FALSE when vtSema is FALSE
1377 if (output
->funcs
->mode_valid(output
, &mode
) != MODE_OK
)
1383 xf86RandR12ModeDestroy(ScreenPtr pScreen
, RRModePtr randr_mode
)
1388 * Given a list of xf86 modes and a RandR Output object, construct
1389 * RandR modes and assign them to the output
1392 xf86RROutputSetModes(RROutputPtr randr_output
, DisplayModePtr modes
)
1394 DisplayModePtr mode
;
1395 RRModePtr
*rrmodes
= NULL
;
1401 for (mode
= modes
; mode
; mode
= mode
->next
)
1405 rrmodes
= malloc(nmode
* sizeof(RRModePtr
));
1411 for (pref
= 1; pref
>= 0; pref
--) {
1412 for (mode
= modes
; mode
; mode
= mode
->next
) {
1413 if ((pref
!= 0) == ((mode
->type
& M_T_PREFERRED
) != 0)) {
1414 xRRModeInfo modeInfo
;
1417 modeInfo
.nameLength
= strlen(mode
->name
);
1418 modeInfo
.width
= mode
->HDisplay
;
1419 modeInfo
.dotClock
= mode
->Clock
* 1000;
1420 modeInfo
.hSyncStart
= mode
->HSyncStart
;
1421 modeInfo
.hSyncEnd
= mode
->HSyncEnd
;
1422 modeInfo
.hTotal
= mode
->HTotal
;
1423 modeInfo
.hSkew
= mode
->HSkew
;
1425 modeInfo
.height
= mode
->VDisplay
;
1426 modeInfo
.vSyncStart
= mode
->VSyncStart
;
1427 modeInfo
.vSyncEnd
= mode
->VSyncEnd
;
1428 modeInfo
.vTotal
= mode
->VTotal
;
1429 modeInfo
.modeFlags
= mode
->Flags
;
1431 rrmode
= RRModeGet(&modeInfo
, mode
->name
);
1433 rrmodes
[nmode
++] = rrmode
;
1441 ret
= RROutputSetModes(randr_output
, rrmodes
, nmode
, npreferred
);
1447 * Mirror the current mode configuration to RandR
1450 xf86RandR12SetInfo12(ScreenPtr pScreen
)
1452 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1453 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1454 RROutputPtr
*clones
;
1458 RRCrtcPtr randr_crtc
;
1461 clones
= malloc(config
->num_output
* sizeof(RROutputPtr
));
1462 crtcs
= malloc(config
->num_crtc
* sizeof(RRCrtcPtr
));
1463 for (o
= 0; o
< config
->num_output
; o
++) {
1464 xf86OutputPtr output
= config
->output
[o
];
1467 for (c
= 0; c
< config
->num_crtc
; c
++)
1468 if (output
->possible_crtcs
& (1 << c
))
1469 crtcs
[ncrtc
++] = config
->crtc
[c
]->randr_crtc
;
1472 randr_crtc
= output
->crtc
->randr_crtc
;
1476 if (!RROutputSetCrtcs(output
->randr_output
, crtcs
, ncrtc
)) {
1482 RROutputSetPhysicalSize(output
->randr_output
,
1483 output
->mm_width
, output
->mm_height
);
1484 xf86RROutputSetModes(output
->randr_output
, output
->probed_modes
);
1486 switch (output
->status
) {
1487 case XF86OutputStatusConnected
:
1488 RROutputSetConnection(output
->randr_output
, RR_Connected
);
1490 case XF86OutputStatusDisconnected
:
1491 RROutputSetConnection(output
->randr_output
, RR_Disconnected
);
1493 case XF86OutputStatusUnknown
:
1494 RROutputSetConnection(output
->randr_output
, RR_UnknownConnection
);
1498 RROutputSetSubpixelOrder(output
->randr_output
, output
->subpixel_order
);
1504 for (l
= 0; l
< config
->num_output
; l
++) {
1505 xf86OutputPtr clone
= config
->output
[l
];
1507 if (l
!= o
&& (output
->possible_clones
& (1 << l
)))
1508 clones
[nclone
++] = clone
->randr_output
;
1510 if (!RROutputSetClones(output
->randr_output
, clones
, nclone
)) {
1522 * Query the hardware for the current state, then mirror
1526 xf86RandR12GetInfo12(ScreenPtr pScreen
, Rotation
* rotations
)
1528 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1532 xf86ProbeOutputModes(pScrn
, 0, 0);
1533 xf86SetScrnInfoModes(pScrn
);
1534 return xf86RandR12SetInfo12(pScreen
);
1538 xf86RandR12CreateObjects12(ScreenPtr pScreen
)
1540 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1541 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1551 for (c
= 0; c
< config
->num_crtc
; c
++) {
1552 xf86CrtcPtr crtc
= config
->crtc
[c
];
1554 crtc
->randr_crtc
= RRCrtcCreate(pScreen
, crtc
);
1555 RRCrtcGammaSetSize(crtc
->randr_crtc
, 256);
1560 for (o
= 0; o
< config
->num_output
; o
++) {
1561 xf86OutputPtr output
= config
->output
[o
];
1563 output
->randr_output
= RROutputCreate(pScreen
, output
->name
,
1564 strlen(output
->name
), output
);
1566 if (output
->funcs
->create_resources
!= NULL
)
1567 output
->funcs
->create_resources(output
);
1568 RRPostPendingProperties(output
->randr_output
);
1572 config
->randr_provider
= RRProviderCreate(pScreen
, config
->name
,
1573 strlen(config
->name
));
1575 RRProviderSetCapabilities(config
->randr_provider
, pScrn
->capabilities
);
1582 xf86RandR12CreateScreenResources12(ScreenPtr pScreen
)
1585 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1586 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1588 if (xf86RandR12Key
== NULL
)
1591 for (c
= 0; c
< config
->num_crtc
; c
++)
1592 xf86RandR12CrtcNotify(config
->crtc
[c
]->randr_crtc
);
1594 RRScreenSetSizeRange(pScreen
, config
->minWidth
, config
->minHeight
,
1595 config
->maxWidth
, config
->maxHeight
);
1600 * Something happened within the screen configuration due
1601 * to DGA, VidMode or hot key. Tell RandR
1605 xf86RandR12TellChanged(ScreenPtr pScreen
)
1607 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1608 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1611 if (xf86RandR12Key
== NULL
)
1614 xf86RandR12SetInfo12(pScreen
);
1615 for (c
= 0; c
< config
->num_crtc
; c
++)
1616 xf86RandR12CrtcNotify(config
->crtc
[c
]->randr_crtc
);
1618 RRTellChanged(pScreen
);
1622 xf86RandR12PointerMoved(ScrnInfoPtr pScrn
, int x
, int y
)
1624 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
1625 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1626 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
1629 randrp
->pointerX
= x
;
1630 randrp
->pointerY
= y
;
1631 for (c
= 0; c
< config
->num_crtc
; c
++)
1632 xf86RandR13Pan(config
->crtc
[c
], x
, y
);
1636 xf86RandR13GetPanning(ScreenPtr pScreen
,
1637 RRCrtcPtr randr_crtc
,
1638 BoxPtr totalArea
, BoxPtr trackingArea
, INT16
*border
)
1640 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1642 if (crtc
->version
< 2)
1645 memcpy(totalArea
, &crtc
->panningTotalArea
, sizeof(BoxRec
));
1647 memcpy(trackingArea
, &crtc
->panningTrackingArea
, sizeof(BoxRec
));
1649 memcpy(border
, crtc
->panningBorder
, 4 * sizeof(INT16
));
1655 xf86RandR13SetPanning(ScreenPtr pScreen
,
1656 RRCrtcPtr randr_crtc
,
1657 BoxPtr totalArea
, BoxPtr trackingArea
, INT16
*border
)
1659 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
1660 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1661 BoxRec oldTotalArea
;
1662 BoxRec oldTrackingArea
;
1664 Bool oldPanning
= randrp
->panning
;
1666 if (crtc
->version
< 2)
1669 memcpy(&oldTotalArea
, &crtc
->panningTotalArea
, sizeof(BoxRec
));
1670 memcpy(&oldTrackingArea
, &crtc
->panningTrackingArea
, sizeof(BoxRec
));
1671 memcpy(oldBorder
, crtc
->panningBorder
, 4 * sizeof(INT16
));
1674 memcpy(&crtc
->panningTotalArea
, totalArea
, sizeof(BoxRec
));
1676 memcpy(&crtc
->panningTrackingArea
, trackingArea
, sizeof(BoxRec
));
1678 memcpy(crtc
->panningBorder
, border
, 4 * sizeof(INT16
));
1680 if (xf86RandR13VerifyPanningArea(crtc
, pScreen
->width
, pScreen
->height
)) {
1681 xf86RandR13Pan(crtc
, randrp
->pointerX
, randrp
->pointerY
);
1682 randrp
->panning
= PANNING_ENABLED (crtc
);
1686 /* Restore old settings */
1687 memcpy(&crtc
->panningTotalArea
, &oldTotalArea
, sizeof(BoxRec
));
1688 memcpy(&crtc
->panningTrackingArea
, &oldTrackingArea
, sizeof(BoxRec
));
1689 memcpy(crtc
->panningBorder
, oldBorder
, 4 * sizeof(INT16
));
1690 randrp
->panning
= oldPanning
;
1696 * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers
1697 * any per-crtc setup. You asked for it...
1701 gamma_to_ramp(float gamma
, CARD16
*ramp
, int size
)
1705 for (i
= 0; i
< size
; i
++) {
1707 ramp
[i
] = i
| i
<< 8;
1710 (CARD16
) (pow((double) i
/ (double) (size
- 1), 1. / gamma
)
1711 * (double) (size
- 1) * 257);
1716 xf86RandR12ChangeGamma(ScrnInfoPtr pScrn
, Gamma gamma
)
1718 CARD16
*points
, *red
, *green
, *blue
;
1719 RRCrtcPtr crtc
= xf86CompatRRCrtc(pScrn
);
1725 size
= max(0, crtc
->gammaSize
);
1729 points
= calloc(size
, 3 * sizeof(CARD16
));
1734 green
= points
+ size
;
1735 blue
= points
+ 2 * size
;
1737 gamma_to_ramp(gamma
.red
, red
, size
);
1738 gamma_to_ramp(gamma
.green
, green
, size
);
1739 gamma_to_ramp(gamma
.blue
, blue
, size
);
1740 RRCrtcGammaSet(crtc
, red
, green
, blue
);
1744 pScrn
->gamma
= gamma
;
1750 xf86RandR12EnterVT(ScrnInfoPtr pScrn
)
1752 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
1753 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
1754 rrScrPrivPtr rp
= rrGetScrPriv(pScreen
);
1758 if (randrp
->orig_EnterVT
) {
1759 pScrn
->EnterVT
= randrp
->orig_EnterVT
;
1760 ret
= pScrn
->EnterVT(pScrn
);
1761 randrp
->orig_EnterVT
= pScrn
->EnterVT
;
1762 pScrn
->EnterVT
= xf86RandR12EnterVT
;
1768 for (i
= 0; i
< rp
->numCrtcs
; i
++)
1769 xf86RandR12CrtcSetGamma(pScreen
, rp
->crtcs
[i
]);
1771 return RRGetInfo(pScreen
, TRUE
); /* force a re-probe of outputs and notify clients about changes */
1775 xf86DetachOutputGPU(ScreenPtr pScreen
)
1777 rrScrPrivPtr rp
= rrGetScrPriv(pScreen
);
1780 /* make sure there are no attached shared scanout pixmaps first */
1781 for (i
= 0; i
< rp
->numCrtcs
; i
++)
1782 RRCrtcDetachScanoutPixmap(rp
->crtcs
[i
]);
1784 DetachOutputGPU(pScreen
);
1788 xf86RandR14ProviderSetOutputSource(ScreenPtr pScreen
,
1789 RRProviderPtr provider
,
1790 RRProviderPtr source_provider
)
1792 if (!source_provider
) {
1793 if (provider
->output_source
) {
1794 ScreenPtr cmScreen
= pScreen
->current_master
;
1796 xf86DetachOutputGPU(pScreen
);
1797 AttachUnboundGPU(cmScreen
, pScreen
);
1799 provider
->output_source
= NULL
;
1803 if (provider
->output_source
== source_provider
)
1806 SetRootClip(source_provider
->pScreen
, FALSE
);
1808 DetachUnboundGPU(pScreen
);
1809 AttachOutputGPU(source_provider
->pScreen
, pScreen
);
1811 provider
->output_source
= source_provider
;
1812 SetRootClip(source_provider
->pScreen
, TRUE
);
1817 xf86RandR14ProviderSetOffloadSink(ScreenPtr pScreen
,
1818 RRProviderPtr provider
,
1819 RRProviderPtr sink_provider
)
1821 if (!sink_provider
) {
1822 if (provider
->offload_sink
) {
1823 ScreenPtr cmScreen
= pScreen
->current_master
;
1824 xf86DetachOutputGPU(pScreen
);
1825 AttachUnboundGPU(cmScreen
, pScreen
);
1828 provider
->offload_sink
= NULL
;
1832 if (provider
->offload_sink
== sink_provider
)
1835 DetachUnboundGPU(pScreen
);
1836 AttachOffloadGPU(sink_provider
->pScreen
, pScreen
);
1838 provider
->offload_sink
= sink_provider
;
1843 xf86RandR14ProviderSetProperty(ScreenPtr pScreen
,
1844 RRProviderPtr randr_provider
,
1845 Atom property
, RRPropertyValuePtr value
)
1847 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1848 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1850 /* If we don't have any property handler, then we don't care what the
1851 * user is setting properties to.
1853 if (config
->provider_funcs
->set_property
== NULL
)
1857 * This function gets called even when vtSema is FALSE, as
1858 * drivers will need to remember the correct value to apply
1859 * when the VT switch occurs
1861 return config
->provider_funcs
->set_property(pScrn
, property
, value
);
1865 xf86RandR14ProviderGetProperty(ScreenPtr pScreen
,
1866 RRProviderPtr randr_provider
, Atom property
)
1868 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1869 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(pScrn
);
1871 if (config
->provider_funcs
->get_property
== NULL
)
1874 /* Should be safe even w/o vtSema */
1875 return config
->provider_funcs
->get_property(pScrn
, property
);
1879 xf86CrtcSetScanoutPixmap(RRCrtcPtr randr_crtc
, PixmapPtr pixmap
)
1881 xf86CrtcPtr crtc
= randr_crtc
->devPrivate
;
1882 if (!crtc
->funcs
->set_scanout_pixmap
)
1884 return crtc
->funcs
->set_scanout_pixmap(crtc
, pixmap
);
1888 xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev
, ScreenPtr screen
, int mode
, int *x
, int *y
)
1890 XF86RandRInfoPtr randrp
= XF86RANDRINFO(screen
);
1892 if (randrp
->panning
)
1895 if (randrp
->orig_ConstrainCursorHarder
) {
1896 screen
->ConstrainCursorHarder
= randrp
->orig_ConstrainCursorHarder
;
1897 screen
->ConstrainCursorHarder(dev
, screen
, mode
, x
, y
);
1898 screen
->ConstrainCursorHarder
= xf86RandR13ConstrainCursorHarder
;
1903 xf86RandR14ProviderDestroy(ScreenPtr screen
, RRProviderPtr provider
)
1905 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
1906 xf86CrtcConfigPtr config
= XF86_CRTC_CONFIG_PTR(scrn
);
1908 if (config
->randr_provider
== provider
) {
1909 if (config
->randr_provider
->offload_sink
) {
1910 DetachOffloadGPU(screen
);
1911 config
->randr_provider
->offload_sink
= NULL
;
1912 RRSetChanged(screen
);
1914 else if (config
->randr_provider
->output_source
) {
1915 xf86DetachOutputGPU(screen
);
1916 config
->randr_provider
->output_source
= NULL
;
1917 RRSetChanged(screen
);
1919 else if (screen
->current_master
)
1920 DetachUnboundGPU(screen
);
1922 config
->randr_provider
= NULL
;
1926 xf86RandR12Init12(ScreenPtr pScreen
)
1928 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
1929 rrScrPrivPtr rp
= rrGetScrPriv(pScreen
);
1930 XF86RandRInfoPtr randrp
= XF86RANDRINFO(pScreen
);
1933 rp
->rrGetInfo
= xf86RandR12GetInfo12
;
1934 rp
->rrScreenSetSize
= xf86RandR12ScreenSetSize
;
1935 rp
->rrCrtcSet
= xf86RandR12CrtcSet
;
1936 rp
->rrCrtcSetGamma
= xf86RandR12CrtcSetGamma
;
1937 rp
->rrCrtcGetGamma
= xf86RandR12CrtcGetGamma
;
1938 rp
->rrOutputSetProperty
= xf86RandR12OutputSetProperty
;
1939 rp
->rrOutputValidateMode
= xf86RandR12OutputValidateMode
;
1940 #if RANDR_13_INTERFACE
1941 rp
->rrOutputGetProperty
= xf86RandR13OutputGetProperty
;
1942 rp
->rrGetPanning
= xf86RandR13GetPanning
;
1943 rp
->rrSetPanning
= xf86RandR13SetPanning
;
1945 rp
->rrModeDestroy
= xf86RandR12ModeDestroy
;
1946 rp
->rrSetConfig
= NULL
;
1948 rp
->rrProviderSetOutputSource
= xf86RandR14ProviderSetOutputSource
;
1949 rp
->rrProviderSetOffloadSink
= xf86RandR14ProviderSetOffloadSink
;
1951 rp
->rrProviderSetProperty
= xf86RandR14ProviderSetProperty
;
1952 rp
->rrProviderGetProperty
= xf86RandR14ProviderGetProperty
;
1953 rp
->rrCrtcSetScanoutPixmap
= xf86CrtcSetScanoutPixmap
;
1954 rp
->rrProviderDestroy
= xf86RandR14ProviderDestroy
;
1956 pScrn
->PointerMoved
= xf86RandR12PointerMoved
;
1957 pScrn
->ChangeGamma
= xf86RandR12ChangeGamma
;
1959 randrp
->orig_EnterVT
= pScrn
->EnterVT
;
1960 pScrn
->EnterVT
= xf86RandR12EnterVT
;
1962 randrp
->panning
= FALSE
;
1963 randrp
->orig_ConstrainCursorHarder
= pScreen
->ConstrainCursorHarder
;
1964 pScreen
->ConstrainCursorHarder
= xf86RandR13ConstrainCursorHarder
;
1966 if (!xf86RandR12CreateObjects12(pScreen
))
1970 * Configure output modes
1972 if (!xf86RandR12SetInfo12(pScreen
))
1974 for (i
= 0; i
< rp
->numCrtcs
; i
++) {
1975 xf86RandR12CrtcGetGamma(pScreen
, rp
->crtcs
[i
]);
1983 xf86RandR12PreInit(ScrnInfoPtr pScrn
)