First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / modes / xf86RandR12.c
blobe46d8a01cb93de23c0d005b2443145106ca57943
1 /*
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
20 * OF THIS SOFTWARE.
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
25 #else
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #endif
31 #include "xf86.h"
32 #include "os.h"
33 #include "mibank.h"
34 #include "globals.h"
35 #include "xf86.h"
36 #include "xf86Priv.h"
37 #include "xf86DDC.h"
38 #include "mipointer.h"
39 #include "windowstr.h"
40 #include <randrstr.h>
41 #include <X11/extensions/render.h>
43 #include "xf86Crtc.h"
44 #include "xf86RandR12.h"
46 typedef struct _xf86RandR12Info {
47 int virtualX;
48 int virtualY;
49 int mmWidth;
50 int mmHeight;
51 int maxX;
52 int maxY;
53 Rotation rotation; /* current mode */
54 Rotation supported_rotations; /* driver supported */
55 } XF86RandRInfoRec, *XF86RandRInfoPtr;
57 #ifdef RANDR_12_INTERFACE
58 static Bool xf86RandR12Init12 (ScreenPtr pScreen);
59 static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
60 #endif
62 static int xf86RandR12Index;
63 static int xf86RandR12Generation;
65 #define XF86RANDRINFO(p) \
66 ((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
68 static int
69 xf86RandR12ModeRefresh (DisplayModePtr mode)
71 if (mode->VRefresh)
72 return (int) (mode->VRefresh + 0.5);
73 else
74 return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
77 static Bool
78 xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
80 RRScreenSizePtr pSize;
81 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
82 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
83 DisplayModePtr mode;
84 int refresh0 = 60;
85 int maxX = 0, maxY = 0;
87 *rotations = randrp->supported_rotations;
89 if (randrp->virtualX == -1 || randrp->virtualY == -1)
91 randrp->virtualX = scrp->virtualX;
92 randrp->virtualY = scrp->virtualY;
95 /* Re-probe the outputs for new monitors or modes */
96 if (scrp->vtSema)
98 xf86ProbeOutputModes (scrp, 0, 0);
99 xf86SetScrnInfoModes (scrp);
100 xf86DiDGAReInit (pScreen);
103 for (mode = scrp->modes; ; mode = mode->next)
105 int refresh = xf86RandR12ModeRefresh (mode);
106 if (randrp->maxX == 0 || randrp->maxY == 0)
108 if (maxX < mode->HDisplay)
109 maxX = mode->HDisplay;
110 if (maxY < mode->VDisplay)
111 maxY = mode->VDisplay;
113 if (mode == scrp->modes)
114 refresh0 = refresh;
115 pSize = RRRegisterSize (pScreen,
116 mode->HDisplay, mode->VDisplay,
117 randrp->mmWidth, randrp->mmHeight);
118 if (!pSize)
119 return FALSE;
120 RRRegisterRate (pScreen, pSize, refresh);
122 if (xf86ModesEqual(mode, scrp->currentMode) &&
123 mode->HDisplay == scrp->virtualX &&
124 mode->VDisplay == scrp->virtualY)
126 RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
128 if (mode->next == scrp->modes)
129 break;
132 if (randrp->maxX == 0 || randrp->maxY == 0)
134 randrp->maxX = maxX;
135 randrp->maxY = maxY;
138 if (scrp->currentMode->HDisplay != randrp->virtualX ||
139 scrp->currentMode->VDisplay != randrp->virtualY)
141 pSize = RRRegisterSize (pScreen,
142 randrp->virtualX, randrp->virtualY,
143 randrp->mmWidth,
144 randrp->mmHeight);
145 if (!pSize)
146 return FALSE;
147 RRRegisterRate (pScreen, pSize, refresh0);
148 if (scrp->virtualX == randrp->virtualX &&
149 scrp->virtualY == randrp->virtualY)
151 RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
155 return TRUE;
158 static Bool
159 xf86RandR12SetMode (ScreenPtr pScreen,
160 DisplayModePtr mode,
161 Bool useVirtual,
162 int mmWidth,
163 int mmHeight)
165 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
166 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
167 int oldWidth = pScreen->width;
168 int oldHeight = pScreen->height;
169 int oldmmWidth = pScreen->mmWidth;
170 int oldmmHeight = pScreen->mmHeight;
171 WindowPtr pRoot = WindowTable[pScreen->myNum];
172 DisplayModePtr currentMode = NULL;
173 Bool ret = TRUE;
174 PixmapPtr pspix = NULL;
176 if (pRoot)
177 (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
178 if (useVirtual)
180 scrp->virtualX = randrp->virtualX;
181 scrp->virtualY = randrp->virtualY;
183 else
185 scrp->virtualX = mode->HDisplay;
186 scrp->virtualY = mode->VDisplay;
189 if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
191 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
192 pScreen->width = scrp->virtualY;
193 pScreen->height = scrp->virtualX;
194 pScreen->mmWidth = mmHeight;
195 pScreen->mmHeight = mmWidth;
197 else
199 pScreen->width = scrp->virtualX;
200 pScreen->height = scrp->virtualY;
201 pScreen->mmWidth = mmWidth;
202 pScreen->mmHeight = mmHeight;
204 if (scrp->currentMode == mode) {
205 /* Save current mode */
206 currentMode = scrp->currentMode;
207 /* Reset, just so we ensure the drivers SwitchMode is called */
208 scrp->currentMode = NULL;
211 * We know that if the driver failed to SwitchMode to the rotated
212 * version, then it should revert back to it's prior mode.
214 if (!xf86SwitchMode (pScreen, mode))
216 ret = FALSE;
217 scrp->virtualX = pScreen->width = oldWidth;
218 scrp->virtualY = pScreen->height = oldHeight;
219 pScreen->mmWidth = oldmmWidth;
220 pScreen->mmHeight = oldmmHeight;
221 scrp->currentMode = currentMode;
224 * Get the new Screen pixmap ptr as SwitchMode might have called
225 * ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
226 * Unfortunately.
228 pspix = (*pScreen->GetScreenPixmap) (pScreen);
229 if (pspix->devPrivate.ptr)
230 scrp->pixmapPrivate = pspix->devPrivate;
233 * Make sure the layout is correct
235 xf86ReconfigureLayout();
238 * Make sure the whole screen is visible
240 xf86SetViewport (pScreen, pScreen->width, pScreen->height);
241 xf86SetViewport (pScreen, 0, 0);
242 if (pRoot)
243 (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
244 return ret;
247 _X_EXPORT Bool
248 xf86RandR12SetConfig (ScreenPtr pScreen,
249 Rotation rotation,
250 int rate,
251 RRScreenSizePtr pSize)
253 ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
254 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
255 DisplayModePtr mode;
256 int px, py;
257 Bool useVirtual = FALSE;
258 int maxX = 0, maxY = 0;
259 Rotation oldRotation = randrp->rotation;
261 randrp->rotation = rotation;
263 if (randrp->virtualX == -1 || randrp->virtualY == -1)
265 randrp->virtualX = scrp->virtualX;
266 randrp->virtualY = scrp->virtualY;
269 miPointerPosition (&px, &py);
270 for (mode = scrp->modes; ; mode = mode->next)
272 if (randrp->maxX == 0 || randrp->maxY == 0)
274 if (maxX < mode->HDisplay)
275 maxX = mode->HDisplay;
276 if (maxY < mode->VDisplay)
277 maxY = mode->VDisplay;
279 if (mode->HDisplay == pSize->width &&
280 mode->VDisplay == pSize->height &&
281 (rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
282 break;
283 if (mode->next == scrp->modes)
285 if (pSize->width == randrp->virtualX &&
286 pSize->height == randrp->virtualY)
288 mode = scrp->modes;
289 useVirtual = TRUE;
290 break;
292 if (randrp->maxX == 0 || randrp->maxY == 0)
294 randrp->maxX = maxX;
295 randrp->maxY = maxY;
297 return FALSE;
301 if (randrp->maxX == 0 || randrp->maxY == 0)
303 randrp->maxX = maxX;
304 randrp->maxY = maxY;
307 if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
308 pSize->mmHeight)) {
309 randrp->rotation = oldRotation;
310 return FALSE;
314 * Move the cursor back where it belongs; SwitchMode repositions it
316 if (pScreen == miPointerCurrentScreen ())
318 px = (px >= pScreen->width ? (pScreen->width - 1) : px);
319 py = (py >= pScreen->height ? (pScreen->height - 1) : py);
321 xf86SetViewport(pScreen, px, py);
323 (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
326 return TRUE;
329 static Bool
330 xf86RandR12ScreenSetSize (ScreenPtr pScreen,
331 CARD16 width,
332 CARD16 height,
333 CARD32 mmWidth,
334 CARD32 mmHeight)
336 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
337 ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
338 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
339 WindowPtr pRoot = WindowTable[pScreen->myNum];
340 PixmapPtr pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
341 Bool ret = FALSE;
343 if (randrp->virtualX == -1 || randrp->virtualY == -1)
345 randrp->virtualX = pScrn->virtualX;
346 randrp->virtualY = pScrn->virtualY;
348 if (pRoot)
349 (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
351 /* Let the driver update virtualX and virtualY */
352 if (!(*config->funcs->resize)(pScrn, width, height))
353 goto finish;
355 ret = TRUE;
357 pScreen->width = pScrnPix->drawable.width = width;
358 pScreen->height = pScrnPix->drawable.height = height;
359 pScreen->mmWidth = mmWidth;
360 pScreen->mmHeight = mmHeight;
362 xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
363 xf86SetViewport (pScreen, 0, 0);
365 finish:
366 if (pRoot)
367 (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
368 #if RANDR_12_INTERFACE
369 if (WindowTable[pScreen->myNum] && ret)
370 RRScreenSizeNotify (pScreen);
371 #endif
372 return ret;
375 _X_EXPORT Rotation
376 xf86RandR12GetRotation(ScreenPtr pScreen)
378 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
380 return randrp->rotation;
383 _X_EXPORT Bool
384 xf86RandR12CreateScreenResources (ScreenPtr pScreen)
386 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
387 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
388 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
389 int c;
390 int width, height;
391 int mmWidth, mmHeight;
392 #ifdef PANORAMIX
393 /* XXX disable RandR when using Xinerama */
394 if (!noPanoramiXExtension)
395 return TRUE;
396 #endif
399 * Compute size of screen
401 width = 0; height = 0;
402 for (c = 0; c < config->num_crtc; c++)
404 xf86CrtcPtr crtc = config->crtc[c];
405 int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
406 int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
408 if (crtc->enabled && crtc_width > width)
409 width = crtc_width;
410 if (crtc->enabled && crtc_height > height)
411 height = crtc_height;
414 if (width && height)
417 * Compute physical size of screen
419 if (monitorResolution)
421 mmWidth = width * 25.4 / monitorResolution;
422 mmHeight = height * 25.4 / monitorResolution;
424 else
426 xf86OutputPtr output = config->output[config->compat_output];
427 xf86CrtcPtr crtc = output->crtc;
429 if (crtc && crtc->mode.HDisplay &&
430 output->mm_width && output->mm_height)
433 * If the output has a mode and a declared size, use that
434 * to scale the screen size
436 DisplayModePtr mode = &crtc->mode;
437 mmWidth = output->mm_width * width / mode->HDisplay;
438 mmHeight = output->mm_height * height / mode->VDisplay;
440 else
443 * Otherwise, just set the screen to 96dpi
445 mmWidth = width * 25.4 / 96;
446 mmHeight = height * 25.4 / 96;
449 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
450 "Setting screen physical size to %d x %d\n",
451 mmWidth, mmHeight);
452 xf86RandR12ScreenSetSize (pScreen,
453 width,
454 height,
455 mmWidth,
456 mmHeight);
459 if (randrp->virtualX == -1 || randrp->virtualY == -1)
461 randrp->virtualX = pScrn->virtualX;
462 randrp->virtualY = pScrn->virtualY;
464 xf86CrtcSetScreenSubpixelOrder (pScreen);
465 #if RANDR_12_INTERFACE
466 if (xf86RandR12CreateScreenResources12 (pScreen))
467 return TRUE;
468 #endif
469 return TRUE;
473 _X_EXPORT Bool
474 xf86RandR12Init (ScreenPtr pScreen)
476 rrScrPrivPtr rp;
477 XF86RandRInfoPtr randrp;
479 #ifdef PANORAMIX
480 /* XXX disable RandR when using Xinerama */
481 if (!noPanoramiXExtension)
482 return TRUE;
483 #endif
484 if (xf86RandR12Generation != serverGeneration)
486 xf86RandR12Index = AllocateScreenPrivateIndex();
487 xf86RandR12Generation = serverGeneration;
490 randrp = xalloc (sizeof (XF86RandRInfoRec));
491 if (!randrp)
492 return FALSE;
494 if (!RRScreenInit(pScreen))
496 xfree (randrp);
497 return FALSE;
499 rp = rrGetScrPriv(pScreen);
500 rp->rrGetInfo = xf86RandR12GetInfo;
501 rp->rrSetConfig = xf86RandR12SetConfig;
503 randrp->virtualX = -1;
504 randrp->virtualY = -1;
505 randrp->mmWidth = pScreen->mmWidth;
506 randrp->mmHeight = pScreen->mmHeight;
508 randrp->rotation = RR_Rotate_0; /* initial rotated mode */
510 randrp->supported_rotations = RR_Rotate_0;
512 randrp->maxX = randrp->maxY = 0;
514 pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
516 #if RANDR_12_INTERFACE
517 if (!xf86RandR12Init12 (pScreen))
518 return FALSE;
519 #endif
520 return TRUE;
523 _X_EXPORT void
524 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
526 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
527 #if RANDR_12_INTERFACE
528 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
529 int c;
530 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
532 for (c = 0; c < config->num_crtc; c++) {
533 xf86CrtcPtr crtc = config->crtc[c];
535 RRCrtcSetRotations (crtc->randr_crtc, rotations);
537 #endif
538 randrp->supported_rotations = rotations;
541 _X_EXPORT void
542 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
544 ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
546 if (xf86RandR12Generation != serverGeneration ||
547 XF86RANDRINFO(pScreen)->virtualX == -1)
549 *x = pScrn->virtualX;
550 *y = pScrn->virtualY;
551 } else {
552 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
554 *x = randrp->virtualX;
555 *y = randrp->virtualY;
559 #if RANDR_12_INTERFACE
561 #define FLAG_BITS (RR_HSyncPositive | \
562 RR_HSyncNegative | \
563 RR_VSyncPositive | \
564 RR_VSyncNegative | \
565 RR_Interlace | \
566 RR_DoubleScan | \
567 RR_CSync | \
568 RR_CSyncPositive | \
569 RR_CSyncNegative | \
570 RR_HSkewPresent | \
571 RR_BCast | \
572 RR_PixelMultiplex | \
573 RR_DoubleClock | \
574 RR_ClockDivideBy2)
576 static Bool
577 xf86RandRModeMatches (RRModePtr randr_mode,
578 DisplayModePtr mode)
580 #if 0
581 if (match_name)
583 /* check for same name */
584 int len = strlen (mode->name);
585 if (randr_mode->mode.nameLength != len) return FALSE;
586 if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE;
588 #endif
590 /* check for same timings */
591 if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE;
592 if (randr_mode->mode.width != mode->HDisplay) return FALSE;
593 if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE;
594 if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE;
595 if (randr_mode->mode.hTotal != mode->HTotal) return FALSE;
596 if (randr_mode->mode.hSkew != mode->HSkew) return FALSE;
597 if (randr_mode->mode.height != mode->VDisplay) return FALSE;
598 if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE;
599 if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE;
600 if (randr_mode->mode.vTotal != mode->VTotal) return FALSE;
602 /* check for same flags (using only the XF86 valid flag bits) */
603 if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
604 return FALSE;
606 /* everything matches */
607 return TRUE;
610 static Bool
611 xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
613 ScreenPtr pScreen = randr_crtc->pScreen;
614 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
615 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
616 RRModePtr randr_mode = NULL;
617 int x;
618 int y;
619 Rotation rotation;
620 int numOutputs;
621 RROutputPtr *randr_outputs;
622 RROutputPtr randr_output;
623 xf86CrtcPtr crtc = randr_crtc->devPrivate;
624 xf86OutputPtr output;
625 int i, j;
626 DisplayModePtr mode = &crtc->mode;
627 Bool ret;
629 randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
630 if (!randr_outputs)
631 return FALSE;
632 x = crtc->x;
633 y = crtc->y;
634 rotation = crtc->rotation;
635 numOutputs = 0;
636 randr_mode = NULL;
637 for (i = 0; i < config->num_output; i++)
639 output = config->output[i];
640 if (output->crtc == crtc)
642 randr_output = output->randr_output;
643 randr_outputs[numOutputs++] = randr_output;
645 * We make copies of modes, so pointer equality
646 * isn't sufficient
648 for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++)
650 RRModePtr m = (j < randr_output->numModes ?
651 randr_output->modes[j] :
652 randr_output->userModes[j-randr_output->numModes]);
654 if (xf86RandRModeMatches (m, mode))
656 randr_mode = m;
657 break;
662 ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
663 rotation, numOutputs, randr_outputs);
664 DEALLOCATE_LOCAL(randr_outputs);
665 return ret;
669 * Convert a RandR mode to a DisplayMode
671 static void
672 xf86RandRModeConvert (ScrnInfoPtr scrn,
673 RRModePtr randr_mode,
674 DisplayModePtr mode)
676 mode->prev = NULL;
677 mode->next = NULL;
678 mode->name = NULL;
679 mode->status = MODE_OK;
680 mode->type = 0;
682 mode->Clock = randr_mode->mode.dotClock / 1000;
684 mode->HDisplay = randr_mode->mode.width;
685 mode->HSyncStart = randr_mode->mode.hSyncStart;
686 mode->HSyncEnd = randr_mode->mode.hSyncEnd;
687 mode->HTotal = randr_mode->mode.hTotal;
688 mode->HSkew = randr_mode->mode.hSkew;
690 mode->VDisplay = randr_mode->mode.height;
691 mode->VSyncStart = randr_mode->mode.vSyncStart;
692 mode->VSyncEnd = randr_mode->mode.vSyncEnd;
693 mode->VTotal = randr_mode->mode.vTotal;
694 mode->VScan = 0;
696 mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
698 xf86SetModeCrtc (mode, scrn->adjustFlags);
701 static Bool
702 xf86RandR12CrtcSet (ScreenPtr pScreen,
703 RRCrtcPtr randr_crtc,
704 RRModePtr randr_mode,
705 int x,
706 int y,
707 Rotation rotation,
708 int num_randr_outputs,
709 RROutputPtr *randr_outputs)
711 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
712 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
713 xf86CrtcPtr crtc = randr_crtc->devPrivate;
714 Bool changed = FALSE;
715 int o, ro;
716 xf86CrtcPtr *save_crtcs;
717 Bool save_enabled = crtc->enabled;
719 save_crtcs = ALLOCATE_LOCAL(config->num_output * sizeof (xf86CrtcPtr));
720 if ((randr_mode != NULL) != crtc->enabled)
721 changed = TRUE;
722 else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
723 changed = TRUE;
725 if (rotation != crtc->rotation)
726 changed = TRUE;
728 if (x != crtc->x || y != crtc->y)
729 changed = TRUE;
730 for (o = 0; o < config->num_output; o++)
732 xf86OutputPtr output = config->output[o];
733 xf86CrtcPtr new_crtc;
735 save_crtcs[o] = output->crtc;
737 if (output->crtc == crtc)
738 new_crtc = NULL;
739 else
740 new_crtc = output->crtc;
741 for (ro = 0; ro < num_randr_outputs; ro++)
742 if (output->randr_output == randr_outputs[ro])
744 new_crtc = crtc;
745 break;
747 if (new_crtc != output->crtc)
749 changed = TRUE;
750 output->crtc = new_crtc;
753 for (ro = 0; ro < num_randr_outputs; ro++)
754 if (randr_outputs[ro]->pendingProperties)
755 changed = TRUE;
757 /* XXX need device-independent mode setting code through an API */
758 if (changed)
760 crtc->enabled = randr_mode != NULL;
762 if (randr_mode)
764 DisplayModeRec mode;
766 xf86RandRModeConvert (pScrn, randr_mode, &mode);
767 if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y))
769 crtc->enabled = save_enabled;
770 for (o = 0; o < config->num_output; o++)
772 xf86OutputPtr output = config->output[o];
773 output->crtc = save_crtcs[o];
775 DEALLOCATE_LOCAL(save_crtcs);
776 return FALSE;
779 * Save the last successful setting for EnterVT
781 crtc->desiredMode = mode;
782 crtc->desiredRotation = rotation;
783 crtc->desiredX = x;
784 crtc->desiredY = y;
786 xf86DisableUnusedFunctions (pScrn);
788 DEALLOCATE_LOCAL(save_crtcs);
789 return xf86RandR12CrtcNotify (randr_crtc);
792 static Bool
793 xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
794 RRCrtcPtr randr_crtc)
796 xf86CrtcPtr crtc = randr_crtc->devPrivate;
798 if (crtc->funcs->gamma_set == NULL)
799 return FALSE;
801 if (!crtc->scrn->vtSema)
802 return TRUE;
804 crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
805 randr_crtc->gammaBlue, randr_crtc->gammaSize);
807 return TRUE;
810 static Bool
811 xf86RandR12OutputSetProperty (ScreenPtr pScreen,
812 RROutputPtr randr_output,
813 Atom property,
814 RRPropertyValuePtr value)
816 xf86OutputPtr output = randr_output->devPrivate;
818 /* If we don't have any property handler, then we don't care what the
819 * user is setting properties to.
821 if (output->funcs->set_property == NULL)
822 return TRUE;
825 * This function gets called even when vtSema is FALSE, as
826 * drivers will need to remember the correct value to apply
827 * when the VT switch occurs
829 return output->funcs->set_property(output, property, value);
832 static Bool
833 xf86RandR12OutputValidateMode (ScreenPtr pScreen,
834 RROutputPtr randr_output,
835 RRModePtr randr_mode)
837 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
838 xf86OutputPtr output = randr_output->devPrivate;
839 DisplayModeRec mode;
841 xf86RandRModeConvert (pScrn, randr_mode, &mode);
843 * This function may be called when vtSema is FALSE, so
844 * the underlying function must either avoid touching the hardware
845 * or return FALSE when vtSema is FALSE
847 if (output->funcs->mode_valid (output, &mode) != MODE_OK)
848 return FALSE;
849 return TRUE;
852 static void
853 xf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode)
858 * Given a list of xf86 modes and a RandR Output object, construct
859 * RandR modes and assign them to the output
861 static Bool
862 xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
864 DisplayModePtr mode;
865 RRModePtr *rrmodes = NULL;
866 int nmode = 0;
867 int npreferred = 0;
868 Bool ret = TRUE;
869 int pref;
871 for (mode = modes; mode; mode = mode->next)
872 nmode++;
874 if (nmode) {
875 rrmodes = xalloc (nmode * sizeof (RRModePtr));
877 if (!rrmodes)
878 return FALSE;
879 nmode = 0;
881 for (pref = 1; pref >= 0; pref--) {
882 for (mode = modes; mode; mode = mode->next) {
883 if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
884 xRRModeInfo modeInfo;
885 RRModePtr rrmode;
887 modeInfo.nameLength = strlen (mode->name);
888 modeInfo.width = mode->HDisplay;
889 modeInfo.dotClock = mode->Clock * 1000;
890 modeInfo.hSyncStart = mode->HSyncStart;
891 modeInfo.hSyncEnd = mode->HSyncEnd;
892 modeInfo.hTotal = mode->HTotal;
893 modeInfo.hSkew = mode->HSkew;
895 modeInfo.height = mode->VDisplay;
896 modeInfo.vSyncStart = mode->VSyncStart;
897 modeInfo.vSyncEnd = mode->VSyncEnd;
898 modeInfo.vTotal = mode->VTotal;
899 modeInfo.modeFlags = mode->Flags;
901 rrmode = RRModeGet (&modeInfo, mode->name);
902 if (rrmode) {
903 rrmodes[nmode++] = rrmode;
904 npreferred += pref;
911 ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
912 xfree (rrmodes);
913 return ret;
917 * Mirror the current mode configuration to RandR
919 static Bool
920 xf86RandR12SetInfo12 (ScreenPtr pScreen)
922 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
923 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
924 RROutputPtr *clones;
925 RRCrtcPtr *crtcs;
926 int ncrtc;
927 int o, c, l;
928 RRCrtcPtr randr_crtc;
929 int nclone;
931 clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
932 crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
933 for (o = 0; o < config->num_output; o++)
935 xf86OutputPtr output = config->output[o];
937 ncrtc = 0;
938 for (c = 0; c < config->num_crtc; c++)
939 if (output->possible_crtcs & (1 << c))
940 crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
942 if (output->crtc)
943 randr_crtc = output->crtc->randr_crtc;
944 else
945 randr_crtc = NULL;
947 if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
949 DEALLOCATE_LOCAL (crtcs);
950 DEALLOCATE_LOCAL (clones);
951 return FALSE;
954 RROutputSetPhysicalSize(output->randr_output,
955 output->mm_width,
956 output->mm_height);
957 xf86RROutputSetModes (output->randr_output, output->probed_modes);
959 switch (output->status) {
960 case XF86OutputStatusConnected:
961 RROutputSetConnection (output->randr_output, RR_Connected);
962 break;
963 case XF86OutputStatusDisconnected:
964 RROutputSetConnection (output->randr_output, RR_Disconnected);
965 break;
966 case XF86OutputStatusUnknown:
967 RROutputSetConnection (output->randr_output, RR_UnknownConnection);
968 break;
971 RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
974 * Valid clones
976 nclone = 0;
977 for (l = 0; l < config->num_output; l++)
979 xf86OutputPtr clone = config->output[l];
981 if (l != o && (output->possible_clones & (1 << l)))
982 clones[nclone++] = clone->randr_output;
984 if (!RROutputSetClones (output->randr_output, clones, nclone))
986 DEALLOCATE_LOCAL (crtcs);
987 DEALLOCATE_LOCAL (clones);
988 return FALSE;
991 DEALLOCATE_LOCAL (crtcs);
992 DEALLOCATE_LOCAL (clones);
993 return TRUE;
999 * Query the hardware for the current state, then mirror
1000 * that to RandR
1002 static Bool
1003 xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
1005 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1007 if (!pScrn->vtSema)
1008 return TRUE;
1009 xf86ProbeOutputModes (pScrn, 0, 0);
1010 xf86SetScrnInfoModes (pScrn);
1011 xf86DiDGAReInit (pScreen);
1012 return xf86RandR12SetInfo12 (pScreen);
1015 static Bool
1016 xf86RandR12CreateObjects12 (ScreenPtr pScreen)
1018 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1019 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1020 int c;
1021 int o;
1023 if (!RRInit ())
1024 return FALSE;
1027 * Configure crtcs
1029 for (c = 0; c < config->num_crtc; c++)
1031 xf86CrtcPtr crtc = config->crtc[c];
1033 crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
1034 RRCrtcGammaSetSize (crtc->randr_crtc, 256);
1037 * Configure outputs
1039 for (o = 0; o < config->num_output; o++)
1041 xf86OutputPtr output = config->output[o];
1043 output->randr_output = RROutputCreate (pScreen, output->name,
1044 strlen (output->name),
1045 output);
1047 if (output->funcs->create_resources != NULL)
1048 output->funcs->create_resources(output);
1049 RRPostPendingProperties (output->randr_output);
1051 return TRUE;
1054 static Bool
1055 xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
1057 int c;
1058 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1059 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1061 for (c = 0; c < config->num_crtc; c++)
1062 xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
1065 RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
1066 config->maxWidth, config->maxHeight);
1067 return TRUE;
1071 * Something happened within the screen configuration due
1072 * to DGA, VidMode or hot key. Tell RandR
1075 _X_EXPORT void
1076 xf86RandR12TellChanged (ScreenPtr pScreen)
1078 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1079 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1080 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1081 int c;
1083 if (!randrp)
1084 return;
1085 xf86RandR12SetInfo12 (pScreen);
1086 for (c = 0; c < config->num_crtc; c++)
1087 xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
1089 RRTellChanged (pScreen);
1092 static void
1093 xf86RandR12PointerMoved (int scrnIndex, int x, int y)
1097 static Bool
1098 xf86RandR12Init12 (ScreenPtr pScreen)
1100 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1101 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1103 rp->rrGetInfo = xf86RandR12GetInfo12;
1104 rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
1105 rp->rrCrtcSet = xf86RandR12CrtcSet;
1106 rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
1107 rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
1108 rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
1109 rp->rrModeDestroy = xf86RandR12ModeDestroy;
1110 rp->rrSetConfig = NULL;
1111 pScrn->PointerMoved = xf86RandR12PointerMoved;
1112 if (!xf86RandR12CreateObjects12 (pScreen))
1113 return FALSE;
1116 * Configure output modes
1118 if (!xf86RandR12SetInfo12 (pScreen))
1119 return FALSE;
1120 return TRUE;
1123 #endif
1125 _X_EXPORT Bool
1126 xf86RandR12PreInit (ScrnInfoPtr pScrn)
1128 return TRUE;