diff options
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r-- | randr/rrcrtc.c | 238 |
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; +} |