summaryrefslogtreecommitdiff
path: root/hw/xfree86/common/xf86RandR.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/xfree86/common/xf86RandR.c')
-rw-r--r--hw/xfree86/common/xf86RandR.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
new file mode 100644
index 000000000..c2dbcc170
--- /dev/null
+++ b/hw/xfree86/common/xf86RandR.c
@@ -0,0 +1,280 @@
+/*
+ * $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.4 2003/02/13 10:49:38 eich Exp $
+ *
+ * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "X.h"
+#include "os.h"
+#include "mibank.h"
+#include "globals.h"
+#include "xf86.h"
+#include "xf86Priv.h"
+#include "xf86DDC.h"
+#include "mipointer.h"
+#include <randrstr.h>
+
+typedef struct _xf86RandRInfo {
+ CreateScreenResourcesProcPtr CreateScreenResources;
+ CloseScreenProcPtr CloseScreen;
+ int virtualX;
+ int virtualY;
+} XF86RandRInfoRec, *XF86RandRInfoPtr;
+
+static int xf86RandRIndex;
+static int xf86RandRGeneration;
+
+#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[xf86RandRIndex].ptr)
+
+static int
+xf86RandRModeRefresh (DisplayModePtr mode)
+{
+ if (mode->VRefresh)
+ return (int) mode->VRefresh;
+ else
+ return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal);
+}
+
+static Bool
+xf86RandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ RRScreenSizePtr pSize;
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ Bool reportVirtual = TRUE;
+ int refresh0 = 60;
+
+ *rotations = RR_Rotate_0;
+
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ int refresh = xf86RandRModeRefresh (mode);
+ if (mode == scrp->modes)
+ refresh0 = refresh;
+ pSize = RRRegisterSize (pScreen,
+ mode->HDisplay, mode->VDisplay,
+ pScreen->mmWidth, pScreen->mmHeight);
+ if (!pSize)
+ return FALSE;
+ if (mode->HDisplay == randrp->virtualX &&
+ mode->VDisplay == randrp->virtualY)
+ reportVirtual = FALSE;
+ RRRegisterRate (pScreen, pSize, refresh);
+ if (mode == scrp->currentMode &&
+ mode->HDisplay == pScreen->width && mode->VDisplay == pScreen->height)
+ RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh, pSize);
+ if (mode->next == scrp->modes)
+ break;
+ }
+ if (reportVirtual)
+ {
+ mode = scrp->modes;
+ pSize = RRRegisterSize (pScreen,
+ randrp->virtualX, randrp->virtualY,
+ pScreen->mmWidth * randrp->virtualX / mode->HDisplay,
+ pScreen->mmHeight * randrp->virtualY / mode->VDisplay);
+ if (!pSize)
+ return FALSE;
+ RRRegisterRate (pScreen, pSize, refresh0);
+ if (pScreen->width == randrp->virtualX &&
+ pScreen->height == randrp->virtualY)
+ {
+ RRSetCurrentConfig (pScreen, RR_Rotate_0, refresh0, pSize);
+ }
+ }
+ return TRUE;
+}
+
+static Bool
+xf86RandRSetMode (ScreenPtr pScreen,
+ DisplayModePtr mode,
+ Bool useVirtual)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ int oldWidth = pScreen->width;
+ int oldHeight = pScreen->height;
+ WindowPtr pRoot = WindowTable[pScreen->myNum];
+
+ if (pRoot)
+ xf86EnableDisableFBAccess (pScreen->myNum, FALSE);
+ if (useVirtual)
+ {
+ scrp->virtualX = randrp->virtualX;
+ scrp->virtualY = randrp->virtualY;
+ }
+ else
+ {
+ scrp->virtualX = mode->HDisplay;
+ scrp->virtualY = mode->VDisplay;
+ }
+ pScreen->width = scrp->virtualX;
+ pScreen->height = scrp->virtualY;
+ if (!xf86SwitchMode (pScreen, mode))
+ {
+ scrp->virtualX = pScreen->width = oldWidth;
+ scrp->virtualY = pScreen->height = oldHeight;
+ return FALSE;
+ }
+ /*
+ * Make sure the layout is correct
+ */
+ xf86ReconfigureLayout();
+
+ /*
+ * Make sure the whole screen is visible
+ */
+ xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+ xf86SetViewport (pScreen, 0, 0);
+ if (pRoot)
+ xf86EnableDisableFBAccess (pScreen->myNum, TRUE);
+ return TRUE;
+}
+
+static Bool
+xf86RandRSetConfig (ScreenPtr pScreen,
+ Rotation rotation,
+ int rate,
+ RRScreenSizePtr pSize)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+ int px, py;
+ Bool useVirtual = FALSE;
+
+ miPointerPosition (&px, &py);
+ for (mode = scrp->modes; ; mode = mode->next)
+ {
+ if (mode->HDisplay == pSize->width &&
+ mode->VDisplay == pSize->height &&
+ (rate == 0 || xf86RandRModeRefresh (mode) == rate))
+ break;
+ if (mode->next == scrp->modes)
+ {
+ if (pSize->width == randrp->virtualX &&
+ pSize->height == randrp->virtualY)
+ {
+ mode = scrp->modes;
+ useVirtual = TRUE;
+ break;
+ }
+ return FALSE;
+ }
+ }
+ if (!xf86RandRSetMode (pScreen, mode, useVirtual))
+ return FALSE;
+ /*
+ * Move the cursor back where it belongs; SwitchMode repositions it
+ */
+ if (pScreen == miPointerCurrentScreen ())
+ {
+ if (px < pSize->width && py < pSize->height)
+ (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
+ }
+ return TRUE;
+}
+
+/*
+ * Wait until the screen is initialized before whacking the
+ * sizes around; otherwise the screen pixmap will be allocated
+ * at the current mode size rather than the maximum size
+ */
+static Bool
+xf86RandRCreateScreenResources (ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+ DisplayModePtr mode;
+
+ pScreen->CreateScreenResources = randrp->CreateScreenResources;
+ if (!(*pScreen->CreateScreenResources) (pScreen))
+ return FALSE;
+
+ mode = scrp->currentMode;
+ if (mode)
+ xf86RandRSetMode (pScreen, mode, TRUE);
+
+ return TRUE;
+}
+
+/*
+ * Reset size back to original
+ */
+static Bool
+xf86RandRCloseScreen (int index, ScreenPtr pScreen)
+{
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+ XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+
+ scrp->virtualX = pScreen->width = randrp->virtualX;
+ scrp->virtualY = pScreen->height = randrp->virtualY;
+ scrp->currentMode = scrp->modes;
+ pScreen->CloseScreen = randrp->CloseScreen;
+ xfree (randrp);
+ pScreen->devPrivates[xf86RandRIndex].ptr = 0;
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+Bool
+xf86RandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr rp;
+ XF86RandRInfoPtr randrp;
+ ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
+
+#ifdef PANORAMIX
+ /* XXX disable RandR when using Xinerama */
+ if (!noPanoramiXExtension)
+ return TRUE;
+#endif
+ if (xf86RandRGeneration != serverGeneration)
+ {
+ xf86RandRIndex = AllocateScreenPrivateIndex();
+ xf86RandRGeneration = serverGeneration;
+ }
+
+ randrp = xalloc (sizeof (XF86RandRInfoRec));
+ if (!randrp)
+ return FALSE;
+
+ if (!RRScreenInit (pScreen))
+ {
+ xfree (randrp);
+ return FALSE;
+ }
+ rp = rrGetScrPriv(pScreen);
+ rp->rrGetInfo = xf86RandRGetInfo;
+ rp->rrSetConfig = xf86RandRSetConfig;
+
+ randrp->virtualX = scrp->virtualX;
+ randrp->virtualY = scrp->virtualY;
+
+ randrp->CreateScreenResources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = xf86RandRCreateScreenResources;
+
+ randrp->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = xf86RandRCloseScreen;
+
+ pScreen->devPrivates[xf86RandRIndex].ptr = randrp;
+ return TRUE;
+}