summaryrefslogtreecommitdiff
path: root/randr/rrcrtc.c
diff options
context:
space:
mode:
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r--randr/rrcrtc.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
new file mode 100644
index 000000000..cc5b24d50
--- /dev/null
+++ b/randr/rrcrtc.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2006 Keith Packard
+ *
+ * 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 the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS 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 "randrstr.h"
+
+static RESTYPE CrtcType;
+
+/*
+ * Create a CRTC
+ */
+RRCrtcPtr
+RRCrtcCreate (ScreenPtr pScreen,
+ void *devPrivate)
+{
+ rrScrPriv (pScreen);
+ RRCrtcPtr crtc;
+ RRCrtcPtr *crtcs;
+
+ crtc = xalloc (sizeof (RRCrtcRec));
+ if (!crtc)
+ return NULL;
+ if (pScrPriv->numCrtcs)
+ crtcs = xrealloc (pScrPriv->crtcs,
+ (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+ else
+ crtcs = xalloc (sizeof (RRCrtcPtr));
+ if (!crtcs)
+ {
+ xfree (crtc);
+ return NULL;
+ }
+ crtc->id = FakeClientID (0);
+ crtc->pScreen = pScreen;
+ crtc->mode = NULL;
+ crtc->x = 0;
+ crtc->y = 0;
+ crtc->rotation = RR_Rotate_0;
+ crtc->rotations = RR_Rotate_0;
+ crtc->outputs = NULL;
+ crtc->numOutputs = 0;
+ crtc->changed = TRUE;
+ crtc->devPrivate = devPrivate;
+ pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+ return crtc;
+}
+
+/*
+ * Notify the extension that the Crtc has been reconfigured,
+ * the driver calls this whenever it has updated the mode
+ */
+Bool
+RRCrtcNotify (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ rrScrPriv(pScreen);
+ int i, j;
+ int prevNumOutputs = crtc->numOutputs;
+
+ if (numOutputs != prevNumOutputs)
+ {
+ RROutputPtr *outputs;
+
+ if (crtc->numOutputs)
+ outputs = xrealloc (crtc->outputs,
+ numOutputs * sizeof (RROutputPtr));
+ else
+ outputs = xalloc (numOutputs * sizeof (RROutputPtr));
+ if (!outputs)
+ return FALSE;
+ crtc->outputs = outputs;
+ }
+ for (i = 0; i < numOutputs; i++)
+ {
+ for (j = 0; j < crtc->numOutputs; j++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (j != crtc->numOutputs)
+ {
+ outputs[i]->changed = TRUE;
+ crtc->changed = TRUE;
+ }
+ }
+ for (j = 0; j < crtc->numOutputs; j++)
+ {
+ for (i = 0; i < numOutputs; i++)
+ if (outputs[i] == crtc->outputs[j])
+ break;
+ if (i != numOutputs)
+ {
+ crtc->outputs[j]->changed = TRUE;
+ crtc->changed = TRUE;
+ }
+ }
+ if (mode != crtc->mode)
+ {
+ if (crtc->mode)
+ RRModeDestroy (crtc->mode);
+ crtc->mode = mode;
+ mode->refcnt++;
+ crtc->changed = TRUE;
+ }
+ if (x != crtc->x)
+ {
+ crtc->x = x;
+ crtc->changed = TRUE;
+ }
+ if (y != crtc->y)
+ {
+ crtc->y = y;
+ crtc->changed = TRUE;
+ }
+ if (rotation != crtc->rotation)
+ {
+ crtc->rotation = rotation;
+ crtc->changed = TRUE;
+ }
+ if (crtc->changed)
+ pScrPriv->changed = TRUE;
+ return TRUE;
+}
+
+/*
+ * Request that the Crtc be reconfigured
+ */
+Bool
+RRCrtcSet (RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutputs,
+ RROutputPtr *outputs)
+{
+ ScreenPtr pScreen = crtc->pScreen;
+ rrScrPriv(pScreen);
+
+#if RANDR_12_INTERFACE
+ if (pScrPriv->rrCrtcSet)
+ {
+ return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
+ rotation, numOutputs, outputs);
+ }
+#endif
+#if RANDR_10_INTERFACE
+ if (pScrPriv->rrSetConfig)
+ {
+ RRScreenSize size;
+ RRScreenRate rate;
+ Bool ret;
+
+ size.width = mode->mode.width;
+ size.height = mode->mode.height;
+ size.mmWidth = mode->mode.mmWidth;
+ size.mmHeight = mode->mode.mmHeight;
+ size.nRates = 1;
+ rate.rate = RRVerticalRefresh (&mode->mode);
+ size.pRates = &rate;
+ ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+ /*
+ * Old 1.0 interface tied screen size to mode size
+ */
+ if (ret)
+ RRScreenSizeNotify (pScreen);
+ return ret;
+ }
+#endif
+ return FALSE;
+}
+
+/*
+ * Destroy a Crtc at shutdown
+ */
+void
+RRCrtcDestroy (RRCrtcPtr crtc)
+{
+ FreeResource (crtc->id, 0);
+}
+
+static int
+RRCrtcDestroyResource (pointer value, XID pid)
+{
+ RRCrtcPtr crtc = (RRCrtcPtr) value;
+ ScreenPtr pScreen = crtc->pScreen;
+ rrScrPriv(pScreen);
+ int i;
+
+ for (i = 0; i < pScrPriv->numCrtcs; i++)
+ {
+ if (pScrPriv->crtcs[i] == crtc)
+ {
+ memmove (pScrPriv->crtcs, pScrPriv->crtcs + 1,
+ (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
+ --pScrPriv->numCrtcs;
+ }
+ }
+ free (value);
+ return 1;
+}
+
+/*
+ * Initialize crtc type
+ */
+Bool
+RRCrtcInit (void)
+{
+ CrtcType = CreateNewResourceType (RRCrtcDestroyResource);
+ if (!CrtcType)
+ return FALSE;
+#ifdef XResExtension
+ RegisterResourceName (CrtcType, "CRTC");
+#endif
+ return TRUE;
+}