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>
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;
64 } XF86RandRInfoRec, *XF86RandRInfoPtr;
66 #ifdef RANDR_12_INTERFACE
67 static Bool xf86RandR12Init12 (ScreenPtr pScreen);
68 static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
71 static int xf86RandR12Generation;
72 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
74 static DevPrivateKeyRec xf86RandR12KeyRec;
75 static DevPrivateKey xf86RandR12Key;
76 #define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \
77 dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key))
79 #else /* XORG_VERSION_CURRENT < 7.0 */
81 static int xf86RandR12Index;
82 #define XF86RANDRINFO(p) \
83 ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
85 #endif /* XORG_VERSION_CURRENT < 7.0 */
89 xf86RandR12ModeRefresh (DisplayModePtr mode)
92 return (int) (mode->VRefresh + 0.5);
94 return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
97 /* Adapt panning area; return TRUE if panning area was valid without adaption */
99 xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight)
103 if (crtc->version < 2)
106 if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) {
107 /* Panning in X is disabled */
108 if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2)
109 /* Illegal configuration -> fail/disable */
111 crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0;
112 crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0;
113 crtc->panningBorder[0] = crtc->panningBorder[2] = 0;
115 /* Panning in X is enabled */
116 if (crtc->panningTotalArea.x1 < 0) {
117 /* Panning region outside screen -> move inside */
118 crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1;
119 crtc->panningTotalArea.x1 = 0;
122 if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) {
123 /* Panning region smaller than displayed area -> crop to displayed area */
124 crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay;
127 if (crtc->panningTotalArea.x2 > screenWidth) {
128 /* Panning region larger than screen -> move inside, then crop to screen */
129 crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth;
130 crtc->panningTotalArea.x2 = screenWidth;
132 if (crtc->panningTotalArea.x1 < 0)
133 crtc->panningTotalArea.x1 = 0;
135 if (crtc->panningBorder[0] + crtc->panningBorder[2] > 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;
151 /* Panning in Y is enabled */
152 if (crtc->panningTotalArea.y1 < 0) {
153 /* Panning region outside screen -> move inside */
154 crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1;
155 crtc->panningTotalArea.y1 = 0;
158 if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) {
159 /* Panning region smaller than displayed area -> crop to displayed area */
160 crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay;
163 if (crtc->panningTotalArea.y2 > screenHeight) {
164 /* Panning region larger than screen -> move inside, then crop to screen */
165 crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight;
166 crtc->panningTotalArea.y2 = screenHeight;
168 if (crtc->panningTotalArea.y1 < 0)
169 crtc->panningTotalArea.y1 = 0;
171 if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) {
172 /* Borders too large -> set to 0 */
173 crtc->panningBorder[1] = crtc->panningBorder[3] = 0;
182 * The heart of the panning operation:
184 * Given a frame buffer position (fb_x, fb_y),
185 * and a crtc position (crtc_x, crtc_y),
186 * and a transform matrix which maps frame buffer to crtc,
187 * compute a panning position (pan_x, pan_y) that
188 * makes the resulting transform line those two up
192 xf86ComputeCrtcPan (Bool transform_in_use,
193 struct pixman_f_transform *m,
194 double screen_x, double screen_y,
195 double crtc_x, double crtc_y,
196 int old_pan_x, int old_pan_y,
197 int *new_pan_x, int *new_pan_y)
199 if (transform_in_use) {
201 * Given the current transform, M, the current position
202 * on the Screen, S, and the desired position on the CRTC,
203 * C, compute a translation, T, such that:
207 * where T is of the form
214 * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F |
215 * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F |
216 * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F |
220 * Cx F = M00 dx + M01 dy + R0
221 * Cy F = M10 dx + M11 dy + R1
222 * F = M20 dx + M21 dy + R2
224 * Zero out dx, then dy
226 * F (Cx M10 - Cy M00) =
227 * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1
229 * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1
231 * F (Cx M11 - Cy M01) =
232 * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1
234 * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1
236 * Make some temporaries
238 * T = | Cx M10 - Cy M00 |
239 * | Cx M11 - Cy M01 |
241 * U = | M10 M01 - M00 M11 |
242 * | M11 M00 - M01 M10 |
244 * Q = | M10 R0 - M00 R1 |
245 * | M11 R0 - M01 R1 |
247 * P = | M10 - Cy M20 |
250 * W = | M10 M21 - M20 M11 |
251 * | M11 M20 - M21 M10 |
253 * V = | M10 R2 - M20 R1 |
254 * | M11 R2 - M21 R1 |
263 * Solve for F (two ways)
265 * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0
271 * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1
277 * We'll use which ever solution works (denominator != 0)
279 * Finally, solve for dx and dy:
281 * dx = (F T1 - Q1) / U1
282 * dx = (F P1 - V1) / W1
284 * dy = (F T0 - Q0) / U0
285 * dy = (F P0 - V0) / W0
288 double q[2], u[2], t[2], v[2], w[2], p[2];
290 struct pict_f_vector d;
293 /* Get the un-normalized crtc coordinates again */
294 for (i = 0; i < 3; i++)
295 r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2];
297 /* Combine values into temporaries */
298 for (i = 0; i < 2; i++) {
299 q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1];
300 u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i];
301 t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y;
303 v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1];
304 w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i];
305 p[i] = m->m[1][i] - m->m[2][i] * crtc_y;
308 /* Find a way to compute f */
310 for (i = 0; i < 2; i++) {
311 double a = w[i] * q[i] - u[i] * v[i];
312 double b = w[i] * t[i] - u[i] * p[i];
319 /* Solve for the resulting transform vector */
320 for (i = 0; i < 2; i++) {
322 d.v[1-i] = (t[i] * f - q[i]) / u[i];
324 d.v[1-i] = (p[i] * f - v[i]) / w[i];
328 *new_pan_x = old_pan_x - floor (d.v[0] + 0.5);
329 *new_pan_y = old_pan_y - floor (d.v[1] + 0.5);
331 *new_pan_x = screen_x - crtc_x;
332 *new_pan_y = screen_y - crtc_y;
337 xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
343 if (crtc->version < 2)
346 if (! crtc->enabled ||
347 (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 &&
348 crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1))
353 width = crtc->mode.HDisplay;
354 height = crtc->mode.VDisplay;
356 if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 ||
357 (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) &&
358 (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 ||
359 (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2)))
361 struct pict_f_vector c;
364 * Pre-clip the mouse position to the panning area so that we don't
365 * push the crtc outside. This doesn't deal with changes to the
366 * panning values, only mouse position changes.
368 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1)
370 if (x < crtc->panningTotalArea.x1)
371 x = crtc->panningTotalArea.x1;
372 if (x >= crtc->panningTotalArea.x2)
373 x = crtc->panningTotalArea.x2 - 1;
375 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1)
377 if (y < crtc->panningTotalArea.y1)
378 y = crtc->panningTotalArea.y1;
379 if (y >= crtc->panningTotalArea.y2)
380 y = crtc->panningTotalArea.y2 - 1;
386 if (crtc->transform_in_use) {
387 pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c);
393 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
394 if (c.v[0] < crtc->panningBorder[0]) {
395 c.v[0] = crtc->panningBorder[0];
398 if (c.v[0] >= width - crtc->panningBorder[2]) {
399 c.v[0] = width - crtc->panningBorder[2] - 1;
403 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
404 if (c.v[1] < crtc->panningBorder[1]) {
405 c.v[1] = crtc->panningBorder[1];
408 if (c.v[1] >= height - crtc->panningBorder[3]) {
409 c.v[1] = height - crtc->panningBorder[3] - 1;
414 xf86ComputeCrtcPan (crtc->transform_in_use,
415 &crtc->f_framebuffer_to_crtc,
416 x, y, c.v[0], c.v[1],
417 newX, newY, &newX, &newY);
421 * Ensure that the crtc is within the panning region.
423 * XXX This computation only works when we do not have a transform
426 if (!crtc->transform_in_use)
428 /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
429 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
430 if (newX > crtc->panningTotalArea.x2 - width)
431 newX = crtc->panningTotalArea.x2 - width;
432 if (newX < crtc->panningTotalArea.x1)
433 newX = crtc->panningTotalArea.x1;
435 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
436 if (newY > crtc->panningTotalArea.y2 - height)
437 newY = crtc->panningTotalArea.y2 - height;
438 if (newY < crtc->panningTotalArea.y1)
439 newY = crtc->panningTotalArea.y1;
442 if (newX != crtc->x || newY != crtc->y)
443 xf86CrtcSetOrigin (crtc, newX, newY);
447 xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
449 RRScreenSizePtr pSize;
450 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
451 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
454 int maxX = 0, maxY = 0;
456 *rotations = randrp->supported_rotations;
458 if (randrp->virtualX == -1 || randrp->virtualY == -1)
460 randrp->virtualX = scrp->virtualX;
461 randrp->virtualY = scrp->virtualY;
464 /* Re-probe the outputs for new monitors or modes */
467 xf86ProbeOutputModes (scrp, 0, 0);
468 xf86SetScrnInfoModes (scrp);
471 for (mode = scrp->modes; ; mode = mode->next)
473 int refresh = xf86RandR12ModeRefresh (mode);
474 if (randrp->maxX == 0 || randrp->maxY == 0)
476 if (maxX < mode->HDisplay)
477 maxX = mode->HDisplay;
478 if (maxY < mode->VDisplay)
479 maxY = mode->VDisplay;
481 if (mode == scrp->modes)
483 pSize = RRRegisterSize (pScreen,
484 mode->HDisplay, mode->VDisplay,
485 randrp->mmWidth, randrp->mmHeight);
488 RRRegisterRate (pScreen, pSize, refresh);
490 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)
508 xf86RandR12SetMode (ScreenPtr pScreen,
514 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
515 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
516 int oldWidth = pScreen->width;
517 int oldHeight = pScreen->height;
518 int oldmmWidth = pScreen->mmWidth;
519 int oldmmHeight = pScreen->mmHeight;
520 WindowPtr pRoot = pScreen->root;
521 DisplayModePtr currentMode = NULL;
523 PixmapPtr pspix = NULL;
526 (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
529 scrp->virtualX = randrp->virtualX;
530 scrp->virtualY = randrp->virtualY;
534 scrp->virtualX = mode->HDisplay;
535 scrp->virtualY = mode->VDisplay;
538 if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
540 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
541 pScreen->width = scrp->virtualY;
542 pScreen->height = scrp->virtualX;
543 pScreen->mmWidth = mmHeight;
544 pScreen->mmHeight = mmWidth;
548 pScreen->width = scrp->virtualX;
549 pScreen->height = scrp->virtualY;
550 pScreen->mmWidth = mmWidth;
551 pScreen->mmHeight = mmHeight;
553 if (scrp->currentMode == mode) {
554 /* Save current mode */
555 currentMode = scrp->currentMode;
556 /* Reset, just so we ensure the drivers SwitchMode is called */
557 scrp->currentMode = NULL;
560 * We know that if the driver failed to SwitchMode to the rotated
561 * version, then it should revert back to it's prior mode.
563 if (!xf86SwitchMode (pScreen, mode))
566 scrp->virtualX = pScreen->width = oldWidth;
567 scrp->virtualY = pScreen->height = oldHeight;
568 pScreen->mmWidth = oldmmWidth;
569 pScreen->mmHeight = oldmmHeight;
570 scrp->currentMode = currentMode;
573 * Get the new Screen pixmap ptr as SwitchMode might have called
574 * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
577 pspix = (*pScreen->GetScreenPixmap) (pScreen);
578 if (pspix->devPrivate.ptr)
579 scrp->pixmapPrivate = pspix->devPrivate;
582 * Make sure the layout is correct
584 xf86ReconfigureLayout();
587 * Make sure the whole screen is visible
589 xf86SetViewport (pScreen, pScreen->width, pScreen->height);
590 xf86SetViewport (pScreen, 0, 0);
592 (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
597 xf86RandR12SetConfig (ScreenPtr pScreen,
600 RRScreenSizePtr pSize)
602 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
603 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
606 Bool useVirtual = FALSE;
607 int maxX = 0, maxY = 0;
608 Rotation oldRotation = randrp->rotation;
610 randrp->rotation = rotation;
612 if (randrp->virtualX == -1 || randrp->virtualY == -1)
614 randrp->virtualX = scrp->virtualX;
615 randrp->virtualY = scrp->virtualY;
618 miPointerGetPosition (inputInfo.pointer, &px, &py);
619 for (mode = scrp->modes; ; mode = mode->next)
621 if (randrp->maxX == 0 || randrp->maxY == 0)
623 if (maxX < mode->HDisplay)
624 maxX = mode->HDisplay;
625 if (maxY < mode->VDisplay)
626 maxY = mode->VDisplay;
628 if (mode->HDisplay == pSize->width &&
629 mode->VDisplay == pSize->height &&
630 (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
632 if (mode->next == scrp->modes)
634 if (pSize->width == randrp->virtualX &&
635 pSize->height == randrp->virtualY)
641 if (randrp->maxX == 0 || randrp->maxY == 0)
650 if (randrp->maxX == 0 || randrp->maxY == 0)
656 if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
658 randrp->rotation = oldRotation;
663 * Move the cursor back where it belongs; SwitchMode repositions it
665 if (pScreen == miPointerGetScreen(inputInfo.pointer))
667 px = (px >= pScreen->width ? (pScreen->width - 1) : px);
668 py = (py >= pScreen->height ? (pScreen->height - 1) : py);
670 xf86SetViewport(pScreen, px, py);
672 (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE);
679 xf86RandR12ScreenSetSize (ScreenPtr pScreen,
685 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
686 ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
687 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
688 WindowPtr pRoot = pScreen->root;
693 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
694 if (xf86RandR12Key) {
696 if (randrp->virtualX == -1 || randrp->virtualY == -1)
698 randrp->virtualX = pScrn->virtualX;
699 randrp->virtualY = pScrn->virtualY;
701 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
704 if (pRoot && pScrn->vtSema)
705 (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
707 /* Let the driver update virtualX and virtualY */
708 if (!(*config->funcs->resize)(pScrn, width, height))
712 /* Update panning information */
713 for (c = 0; c < config->num_crtc; c++) {
714 xf86CrtcPtr crtc = config->crtc[c];
715 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
716 crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
717 if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
718 crtc->panningTotalArea.x2 += width - pScreen->width;
719 if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
720 crtc->panningTotalArea.y2 += height - pScreen->height;
721 if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1)
722 crtc->panningTrackingArea.x2 += width - pScreen->width;
723 if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1)
724 crtc->panningTrackingArea.y2 += height - pScreen->height;
725 xf86RandR13VerifyPanningArea (crtc, width, height);
726 xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
730 pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
731 pScreen->width = pScrnPix->drawable.width = width;
732 pScreen->height = pScrnPix->drawable.height = height;
733 randrp->mmWidth = pScreen->mmWidth = mmWidth;
734 randrp->mmHeight = pScreen->mmHeight = mmHeight;
736 xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
737 xf86SetViewport (pScreen, 0, 0);
740 if (pRoot && pScrn->vtSema)
741 (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
742 #if RANDR_12_INTERFACE
743 if (xf86RandR12Key && pScreen->root && ret)
744 RRScreenSizeNotify (pScreen);
750 xf86RandR12GetRotation(ScreenPtr pScreen)
752 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
754 return randrp->rotation;
758 xf86RandR12CreateScreenResources (ScreenPtr pScreen)
760 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
761 xf86CrtcConfigPtr config;
762 XF86RandRInfoPtr randrp;
765 int mmWidth, mmHeight;
767 /* XXX disable RandR when using Xinerama */
768 if (!noPanoramiXExtension)
772 config = XF86_CRTC_CONFIG_PTR(pScrn);
773 randrp = XF86RANDRINFO(pScreen);
775 * Compute size of screen
777 width = 0; height = 0;
778 for (c = 0; c < config->num_crtc; c++)
780 xf86CrtcPtr crtc = config->crtc[c];
781 int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
782 int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
785 if (crtc_width > width)
787 if (crtc_height > height)
788 height = crtc_height;
789 if (crtc->panningTotalArea.x2 > width)
790 width = crtc->panningTotalArea.x2;
791 if (crtc->panningTotalArea.y2 > height)
792 height = crtc->panningTotalArea.y2;
799 * Compute physical size of screen
801 if (monitorResolution)
803 mmWidth = width * 25.4 / monitorResolution;
804 mmHeight = height * 25.4 / monitorResolution;
808 xf86OutputPtr output = xf86CompatOutput(pScrn);
811 output->conf_monitor &&
812 (output->conf_monitor->mon_width > 0 &&
813 output->conf_monitor->mon_height > 0))
816 * Prefer user configured DisplaySize
818 mmWidth = output->conf_monitor->mon_width;
819 mmHeight = output->conf_monitor->mon_height;
824 * Otherwise, just set the screen to DEFAULT_DPI
826 mmWidth = width * 25.4 / DEFAULT_DPI;
827 mmHeight = height * 25.4 / DEFAULT_DPI;
830 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
831 "Setting screen physical size to %d x %d\n",
834 * This is the initial setting of the screen size.
835 * We have to pre-set it here, otherwise panning would be adapted
836 * to the new screen size.
838 pScreen->width = width;
839 pScreen->height = height;
840 xf86RandR12ScreenSetSize (pScreen,
847 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
848 if (xf86RandR12Key == NULL)
852 if (randrp->virtualX == -1 || randrp->virtualY == -1)
854 randrp->virtualX = pScrn->virtualX;
855 randrp->virtualY = pScrn->virtualY;
857 xf86CrtcSetScreenSubpixelOrder (pScreen);
858 #if RANDR_12_INTERFACE
859 if (xf86RandR12CreateScreenResources12 (pScreen))
867 xf86RandR12Init (ScreenPtr pScreen)
870 XF86RandRInfoPtr randrp;
873 /* XXX disable RandR when using Xinerama */
874 if (!noPanoramiXExtension)
876 if (xf86NumScreens == 1)
877 noPanoramiXExtension = TRUE;
883 if (xf86RandR12Generation != serverGeneration)
884 xf86RandR12Generation = serverGeneration;
886 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
887 xf86RandR12Key = &xf86RandR12KeyRec;
888 if (!dixRegisterPrivateKey(&xf86RandR12KeyRec, PRIVATE_SCREEN, 0))
891 xf86RandR12Index = AllocateScreenPrivateIndex();
894 randrp = malloc(sizeof (XF86RandRInfoRec));
898 if (!RRScreenInit(pScreen))
903 rp = rrGetScrPriv(pScreen);
904 rp->rrGetInfo = xf86RandR12GetInfo;
905 rp->rrSetConfig = xf86RandR12SetConfig;
907 randrp->virtualX = -1;
908 randrp->virtualY = -1;
909 randrp->mmWidth = pScreen->mmWidth;
910 randrp->mmHeight = pScreen->mmHeight;
912 randrp->rotation = RR_Rotate_0; /* initial rotated mode */
914 randrp->supported_rotations = RR_Rotate_0;
916 randrp->maxX = randrp->maxY = 0;
918 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
919 dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp);
921 pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
924 #if RANDR_12_INTERFACE
925 if (!xf86RandR12Init12 (pScreen))
932 xf86RandR12CloseScreen (ScreenPtr pScreen)
934 XF86RandRInfoPtr randrp;
936 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
937 if (xf86RandR12Key == NULL)
941 randrp = XF86RANDRINFO(pScreen);
942 #if RANDR_12_INTERFACE
943 xf86Screens[pScreen->myNum]->EnterVT = randrp->orig_EnterVT;
950 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
952 XF86RandRInfoPtr randrp;
953 #if RANDR_12_INTERFACE
954 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
956 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
959 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
960 if (xf86RandR12Key == NULL)
964 randrp = XF86RANDRINFO(pScreen);
965 #if RANDR_12_INTERFACE
966 for (c = 0; c < config->num_crtc; c++) {
967 xf86CrtcPtr crtc = config->crtc[c];
969 RRCrtcSetRotations (crtc->randr_crtc, rotations);
972 randrp->supported_rotations = rotations;
976 xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms)
978 XF86RandRInfoPtr randrp;
979 #if RANDR_13_INTERFACE
980 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
982 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
985 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
986 if (xf86RandR12Key == NULL)
990 randrp = XF86RANDRINFO(pScreen);
991 #if RANDR_13_INTERFACE
992 for (c = 0; c < config->num_crtc; c++) {
993 xf86CrtcPtr crtc = config->crtc[c];
995 RRCrtcSetTransformSupport (crtc->randr_crtc, transforms);
1001 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
1003 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
1005 if (xf86RandR12Generation != serverGeneration ||
1006 XF86RANDRINFO(pScreen)->virtualX == -1)
1008 *x = pScrn->virtualX;
1009 *y = pScrn->virtualY;
1011 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1013 *x = randrp->virtualX;
1014 *y = randrp->virtualY;
1018 #if RANDR_12_INTERFACE
1020 #define FLAG_BITS (RR_HSyncPositive | \
1021 RR_HSyncNegative | \
1022 RR_VSyncPositive | \
1023 RR_VSyncNegative | \
1027 RR_CSyncPositive | \
1028 RR_CSyncNegative | \
1031 RR_PixelMultiplex | \
1036 xf86RandRModeMatches (RRModePtr randr_mode,
1037 DisplayModePtr mode)
1042 /* check for same name */
1043 int len = strlen (mode->name);
1044 if (randr_mode->mode.nameLength != len) return FALSE;
1045 if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE;
1049 /* check for same timings */
1050 if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE;
1051 if (randr_mode->mode.width != mode->HDisplay) return FALSE;
1052 if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE;
1053 if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE;
1054 if (randr_mode->mode.hTotal != mode->HTotal) return FALSE;
1055 if (randr_mode->mode.hSkew != mode->HSkew) return FALSE;
1056 if (randr_mode->mode.height != mode->VDisplay) return FALSE;
1057 if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE;
1058 if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE;
1059 if (randr_mode->mode.vTotal != mode->VTotal) return FALSE;
1061 /* check for same flags (using only the XF86 valid flag bits) */
1062 if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
1065 /* everything matches */
1070 xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
1072 ScreenPtr pScreen = randr_crtc->pScreen;
1073 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1074 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1075 RRModePtr randr_mode = NULL;
1080 RROutputPtr *randr_outputs;
1081 RROutputPtr randr_output;
1082 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1083 xf86OutputPtr output;
1085 DisplayModePtr mode = &crtc->mode;
1088 randr_outputs = malloc(config->num_output * sizeof (RROutputPtr));
1093 rotation = crtc->rotation;
1096 for (i = 0; i < config->num_output; i++)
1098 output = config->output[i];
1099 if (output->crtc == crtc)
1101 randr_output = output->randr_output;
1102 randr_outputs[numOutputs++] = randr_output;
1104 * We make copies of modes, so pointer equality
1107 for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++)
1109 RRModePtr m = (j < randr_output->numModes ?
1110 randr_output->modes[j] :
1111 randr_output->userModes[j-randr_output->numModes]);
1113 if (xf86RandRModeMatches (m, mode))
1121 ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
1123 crtc->transformPresent ? &crtc->transform : NULL,
1124 numOutputs, randr_outputs);
1125 free(randr_outputs);
1130 * Convert a RandR mode to a DisplayMode
1133 xf86RandRModeConvert (ScrnInfoPtr scrn,
1134 RRModePtr randr_mode,
1135 DisplayModePtr mode)
1137 memset(mode, 0, sizeof(DisplayModeRec));
1138 mode->status = MODE_OK;
1140 mode->Clock = randr_mode->mode.dotClock / 1000;
1142 mode->HDisplay = randr_mode->mode.width;
1143 mode->HSyncStart = randr_mode->mode.hSyncStart;
1144 mode->HSyncEnd = randr_mode->mode.hSyncEnd;
1145 mode->HTotal = randr_mode->mode.hTotal;
1146 mode->HSkew = randr_mode->mode.hSkew;
1148 mode->VDisplay = randr_mode->mode.height;
1149 mode->VSyncStart = randr_mode->mode.vSyncStart;
1150 mode->VSyncEnd = randr_mode->mode.vSyncEnd;
1151 mode->VTotal = randr_mode->mode.vTotal;
1154 mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
1156 xf86SetModeCrtc (mode, scrn->adjustFlags);
1160 xf86RandR12CrtcSet (ScreenPtr pScreen,
1161 RRCrtcPtr randr_crtc,
1162 RRModePtr randr_mode,
1166 int num_randr_outputs,
1167 RROutputPtr *randr_outputs)
1169 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1170 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1171 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1172 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1173 RRTransformPtr transform;
1174 Bool changed = FALSE;
1176 xf86CrtcPtr *save_crtcs;
1177 Bool save_enabled = crtc->enabled;
1179 if (!crtc->scrn->vtSema)
1182 save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr));
1183 if ((randr_mode != NULL) != crtc->enabled)
1185 else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
1188 if (rotation != crtc->rotation)
1191 transform = RRCrtcGetTransform (randr_crtc);
1192 if ((transform != NULL) != crtc->transformPresent)
1194 else if (transform && memcmp (&transform->transform, &crtc->transform.transform,
1195 sizeof (transform->transform)) != 0)
1198 if (x != crtc->x || y != crtc->y)
1200 for (o = 0; o < config->num_output; o++)
1202 xf86OutputPtr output = config->output[o];
1203 xf86CrtcPtr new_crtc;
1205 save_crtcs[o] = output->crtc;
1207 if (output->crtc == crtc)
1210 new_crtc = output->crtc;
1211 for (ro = 0; ro < num_randr_outputs; ro++)
1212 if (output->randr_output == randr_outputs[ro])
1217 if (new_crtc != output->crtc)
1220 output->crtc = new_crtc;
1223 for (ro = 0; ro < num_randr_outputs; ro++)
1224 if (randr_outputs[ro]->pendingProperties)
1227 /* XXX need device-independent mode setting code through an API */
1230 crtc->enabled = randr_mode != NULL;
1234 DisplayModeRec mode;
1235 RRTransformPtr transform = RRCrtcGetTransform (randr_crtc);
1237 xf86RandRModeConvert (pScrn, randr_mode, &mode);
1238 if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y))
1240 crtc->enabled = save_enabled;
1241 for (o = 0; o < config->num_output; o++)
1243 xf86OutputPtr output = config->output[o];
1244 output->crtc = save_crtcs[o];
1249 xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
1250 xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
1252 * Save the last successful setting for EnterVT
1254 crtc->desiredMode = mode;
1255 crtc->desiredRotation = rotation;
1257 crtc->desiredTransform = *transform;
1258 crtc->desiredTransformPresent = TRUE;
1260 crtc->desiredTransformPresent = FALSE;
1265 xf86DisableUnusedFunctions (pScrn);
1268 return xf86RandR12CrtcNotify (randr_crtc);
1272 xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
1273 RRCrtcPtr randr_crtc)
1275 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1277 if (crtc->funcs->gamma_set == NULL)
1280 if (!crtc->scrn->vtSema)
1283 /* Realloc local gamma if needed. */
1284 if (randr_crtc->gammaSize != crtc->gamma_size) {
1286 tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16));
1289 crtc->gamma_red = tmp_ptr;
1290 crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
1291 crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
1294 crtc->gamma_size = randr_crtc->gammaSize;
1295 memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16));
1296 memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16));
1297 memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16));
1299 /* Only set it when the crtc is actually running.
1300 * Otherwise it will be set when it's activated.
1303 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
1304 crtc->gamma_blue, crtc->gamma_size);
1310 xf86RandR12CrtcGetGamma (ScreenPtr pScreen,
1311 RRCrtcPtr randr_crtc)
1313 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1315 if (!crtc->gamma_size)
1318 if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue)
1321 /* Realloc randr gamma if needed. */
1322 if (randr_crtc->gammaSize != crtc->gamma_size) {
1324 tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16));
1327 randr_crtc->gammaRed = tmp_ptr;
1328 randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size;
1329 randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size;
1331 randr_crtc->gammaSize = crtc->gamma_size;
1332 memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16));
1333 memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16));
1334 memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16));
1340 xf86RandR12OutputSetProperty (ScreenPtr pScreen,
1341 RROutputPtr randr_output,
1343 RRPropertyValuePtr value)
1345 xf86OutputPtr output = randr_output->devPrivate;
1347 /* If we don't have any property handler, then we don't care what the
1348 * user is setting properties to.
1350 if (output->funcs->set_property == NULL)
1354 * This function gets called even when vtSema is FALSE, as
1355 * drivers will need to remember the correct value to apply
1356 * when the VT switch occurs
1358 return output->funcs->set_property(output, property, value);
1362 xf86RandR13OutputGetProperty (ScreenPtr pScreen,
1363 RROutputPtr randr_output,
1366 xf86OutputPtr output = randr_output->devPrivate;
1368 if (output->funcs->get_property == NULL)
1371 /* Should be safe even w/o vtSema */
1372 return output->funcs->get_property(output, property);
1376 xf86RandR12OutputValidateMode (ScreenPtr pScreen,
1377 RROutputPtr randr_output,
1378 RRModePtr randr_mode)
1380 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1381 xf86OutputPtr output = randr_output->devPrivate;
1382 DisplayModeRec mode;
1384 xf86RandRModeConvert (pScrn, randr_mode, &mode);
1386 * This function may be called when vtSema is FALSE, so
1387 * the underlying function must either avoid touching the hardware
1388 * or return FALSE when vtSema is FALSE
1390 if (output->funcs->mode_valid (output, &mode) != MODE_OK)
1396 xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
1401 * Given a list of xf86 modes and a RandR Output object, construct
1402 * RandR modes and assign them to the output
1405 xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
1407 DisplayModePtr mode;
1408 RRModePtr *rrmodes = NULL;
1414 for (mode = modes; mode; mode = mode->next)
1418 rrmodes = malloc(nmode * sizeof (RRModePtr));
1424 for (pref = 1; pref >= 0; pref--) {
1425 for (mode = modes; mode; mode = mode->next) {
1426 if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
1427 xRRModeInfo modeInfo;
1430 modeInfo.nameLength = strlen (mode->name);
1431 modeInfo.width = mode->HDisplay;
1432 modeInfo.dotClock = mode->Clock * 1000;
1433 modeInfo.hSyncStart = mode->HSyncStart;
1434 modeInfo.hSyncEnd = mode->HSyncEnd;
1435 modeInfo.hTotal = mode->HTotal;
1436 modeInfo.hSkew = mode->HSkew;
1438 modeInfo.height = mode->VDisplay;
1439 modeInfo.vSyncStart = mode->VSyncStart;
1440 modeInfo.vSyncEnd = mode->VSyncEnd;
1441 modeInfo.vTotal = mode->VTotal;
1442 modeInfo.modeFlags = mode->Flags;
1444 rrmode = RRModeGet (&modeInfo, mode->name);
1446 rrmodes[nmode++] = rrmode;
1454 ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
1460 * Mirror the current mode configuration to RandR
1463 xf86RandR12SetInfo12 (ScreenPtr pScreen)
1465 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1466 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1467 RROutputPtr *clones;
1471 RRCrtcPtr randr_crtc;
1474 clones = malloc(config->num_output * sizeof (RROutputPtr));
1475 crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr));
1476 for (o = 0; o < config->num_output; o++)
1478 xf86OutputPtr output = config->output[o];
1481 for (c = 0; c < config->num_crtc; c++)
1482 if (output->possible_crtcs & (1 << c))
1483 crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
1486 randr_crtc = output->crtc->randr_crtc;
1490 if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
1497 RROutputSetPhysicalSize(output->randr_output,
1500 xf86RROutputSetModes (output->randr_output, output->probed_modes);
1502 switch (output->status) {
1503 case XF86OutputStatusConnected:
1504 RROutputSetConnection (output->randr_output, RR_Connected);
1506 case XF86OutputStatusDisconnected:
1507 RROutputSetConnection (output->randr_output, RR_Disconnected);
1509 case XF86OutputStatusUnknown:
1510 RROutputSetConnection (output->randr_output, RR_UnknownConnection);
1514 RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
1520 for (l = 0; l < config->num_output; l++)
1522 xf86OutputPtr clone = config->output[l];
1524 if (l != o && (output->possible_clones & (1 << l)))
1525 clones[nclone++] = clone->randr_output;
1527 if (!RROutputSetClones (output->randr_output, clones, nclone))
1542 * Query the hardware for the current state, then mirror
1546 xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
1548 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1552 xf86ProbeOutputModes (pScrn, 0, 0);
1553 xf86SetScrnInfoModes (pScrn);
1554 return xf86RandR12SetInfo12 (pScreen);
1558 xf86RandR12CreateObjects12 (ScreenPtr pScreen)
1560 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1561 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1571 for (c = 0; c < config->num_crtc; c++)
1573 xf86CrtcPtr crtc = config->crtc[c];
1575 crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
1576 RRCrtcGammaSetSize (crtc->randr_crtc, 256);
1581 for (o = 0; o < config->num_output; o++)
1583 xf86OutputPtr output = config->output[o];
1585 output->randr_output = RROutputCreate (pScreen, output->name,
1586 strlen (output->name),
1589 if (output->funcs->create_resources != NULL)
1590 output->funcs->create_resources(output);
1591 RRPostPendingProperties (output->randr_output);
1597 xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
1600 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1601 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1603 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
1604 if (xf86RandR12Key == NULL)
1608 for (c = 0; c < config->num_crtc; c++)
1609 xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
1611 RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
1612 config->maxWidth, config->maxHeight);
1617 * Something happened within the screen configuration due
1618 * to DGA, VidMode or hot key. Tell RandR
1622 xf86RandR12TellChanged (ScreenPtr pScreen)
1624 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1625 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1628 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
1629 if (xf86RandR12Key == NULL)
1632 if (!XF86RANDRINFO(pScreen))
1636 xf86RandR12SetInfo12 (pScreen);
1637 for (c = 0; c < config->num_crtc; c++)
1638 xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
1640 RRTellChanged (pScreen);
1644 xf86RandR12PointerMoved (int scrnIndex, int x, int y)
1646 ScreenPtr pScreen = screenInfo.screens[scrnIndex];
1647 ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
1648 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1649 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1652 randrp->pointerX = x;
1653 randrp->pointerY = y;
1654 for (c = 0; c < config->num_crtc; c++)
1655 xf86RandR13Pan (config->crtc[c], x, y);
1659 xf86RandR13GetPanning (ScreenPtr pScreen,
1660 RRCrtcPtr randr_crtc,
1662 BoxPtr trackingArea,
1665 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1667 if (crtc->version < 2)
1670 memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec));
1672 memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
1674 memcpy (border, crtc->panningBorder, 4*sizeof(INT16));
1680 xf86RandR13SetPanning (ScreenPtr pScreen,
1681 RRCrtcPtr randr_crtc,
1683 BoxPtr trackingArea,
1686 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1687 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1688 BoxRec oldTotalArea;
1689 BoxRec oldTrackingArea;
1693 if (crtc->version < 2)
1696 memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec));
1697 memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
1698 memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16));
1701 memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec));
1703 memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec));
1705 memcpy (crtc->panningBorder, border, 4*sizeof(INT16));
1707 if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) {
1708 xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
1711 /* Restore old settings */
1712 memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec));
1713 memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec));
1714 memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16));
1720 * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers
1721 * any per-crtc setup. You asked for it...
1725 gamma_to_ramp(float gamma, CARD16 *ramp, int size)
1729 for (i = 0; i < size; i++) {
1733 ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma)
1734 * (double)(size - 1) * 256);
1739 xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma)
1741 CARD16 *points, *red, *green, *blue;
1742 ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1743 RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn);
1749 size = max(0, crtc->gammaSize);
1753 points = calloc(size, 3 * sizeof(CARD16));
1758 green = points + size;
1759 blue = points + 2 * size;
1761 gamma_to_ramp(gamma.red, red, size);
1762 gamma_to_ramp(gamma.green, green, size);
1763 gamma_to_ramp(gamma.blue, blue, size);
1764 RRCrtcGammaSet(crtc, red, green, blue);
1768 pScrn->gamma = gamma;
1774 xf86RandR12EnterVT (int screen_index, int flags)
1776 ScreenPtr pScreen = screenInfo.screens[screen_index];
1777 ScrnInfoPtr pScrn = xf86Screens[screen_index];
1778 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1779 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1782 if (randrp->orig_EnterVT) {
1783 pScrn->EnterVT = randrp->orig_EnterVT;
1784 ret = pScrn->EnterVT (screen_index, flags);
1785 randrp->orig_EnterVT = pScrn->EnterVT;
1786 pScrn->EnterVT = xf86RandR12EnterVT;
1793 for (i = 0; i < rp->numCrtcs; i++)
1794 xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]);
1796 return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */
1800 xf86RandR12Init12 (ScreenPtr pScreen)
1802 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1803 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1804 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1807 rp->rrGetInfo = xf86RandR12GetInfo12;
1808 rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
1809 rp->rrCrtcSet = xf86RandR12CrtcSet;
1810 rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
1811 rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma;
1812 rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
1813 rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
1814 #if RANDR_13_INTERFACE
1815 rp->rrOutputGetProperty = xf86RandR13OutputGetProperty;
1816 rp->rrGetPanning = xf86RandR13GetPanning;
1817 rp->rrSetPanning = xf86RandR13SetPanning;
1819 rp->rrModeDestroy = xf86RandR12ModeDestroy;
1820 rp->rrSetConfig = NULL;
1821 pScrn->PointerMoved = xf86RandR12PointerMoved;
1822 pScrn->ChangeGamma = xf86RandR12ChangeGamma;
1824 randrp->orig_EnterVT = pScrn->EnterVT;
1825 pScrn->EnterVT = xf86RandR12EnterVT;
1827 if (!xf86RandR12CreateObjects12 (pScreen))
1831 * Configure output modes
1833 if (!xf86RandR12SetInfo12 (pScreen))
1835 for (i = 0; i < rp->numCrtcs; i++) {
1836 xf86RandR12CrtcGetGamma(pScreen, rp->crtcs[i]);
1844 xf86RandR12PreInit (ScrnInfoPtr pScrn)