123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- /*
- * 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"
- RESTYPE RROutputType;
- /*
- * Notify the output of some change
- */
- void
- RROutputChanged(RROutputPtr output, Bool configChanged)
- {
- ScreenPtr pScreen = output->pScreen;
- output->changed = TRUE;
- if (pScreen) {
- rrScrPriv(pScreen);
- pScrPriv->changed = TRUE;
- if (configChanged)
- pScrPriv->configChanged = TRUE;
- }
- }
- /*
- * Create an output
- */
- RROutputPtr
- RROutputCreate(const char *name, int nameLength, void *devPrivate)
- {
- RROutputPtr output;
- if (!RRInit())
- return NULL;
- output = malloc(sizeof(RROutputRec) + nameLength + 1);
- if (!output)
- return NULL;
- output->id = FakeClientID(0);
- output->pScreen = NULL;
- output->name = (char *) (output + 1);
- output->nameLength = nameLength;
- memcpy(output->name, name, nameLength);
- output->name[nameLength] = '\0';
- output->connection = RR_UnknownConnection;
- output->subpixelOrder = SubPixelUnknown;
- output->mmWidth = 0;
- output->mmHeight = 0;
- output->crtc = NULL;
- output->numCrtcs = 0;
- output->crtcs = NULL;
- output->numClones = 0;
- output->clones = NULL;
- output->numModes = 0;
- output->numPreferred = 0;
- output->modes = NULL;
- output->properties = NULL;
- output->changed = FALSE;
- output->devPrivate = devPrivate;
- if (!AddResource(output->id, RROutputType, (pointer) output))
- return NULL;
- return output;
- }
- /*
- * Attach an Output to a screen. This is done as a separate step
- * so that an xf86-based driver can create Outputs in PreInit
- * before the Screen has been created
- */
- Bool
- RROutputAttachScreen(RROutputPtr output, ScreenPtr pScreen)
- {
- rrScrPriv(pScreen);
- RROutputPtr *outputs;
- if (pScrPriv->numOutputs)
- outputs = realloc(pScrPriv->outputs,
- (pScrPriv->numOutputs + 1) * sizeof(RROutputPtr));
- else
- outputs = malloc(sizeof(RROutputPtr));
- if (!outputs)
- return FALSE;
- output->pScreen = pScreen;
- pScrPriv->outputs = outputs;
- pScrPriv->outputs[pScrPriv->numOutputs++] = output;
- RROutputChanged(output, FALSE);
- return TRUE;
- }
- /*
- * Notify extension that output parameters have been changed
- */
- Bool
- RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
- {
- RROutputPtr *newClones;
- int i;
- if (numClones == output->numClones) {
- for (i = 0; i < numClones; i++)
- if (output->clones[i] != clones[i])
- break;
- if (i == numClones)
- return TRUE;
- }
- if (numClones) {
- newClones = malloc(numClones * sizeof(RROutputPtr));
- if (!newClones)
- return FALSE;
- memcpy(newClones, clones, numClones * sizeof(RROutputPtr));
- }
- else
- newClones = NULL;
- if (output->clones)
- free(output->clones);
- output->clones = newClones;
- output->numClones = numClones;
- RROutputChanged(output, TRUE);
- return TRUE;
- }
- Bool
- RROutputSetModes(RROutputPtr output,
- RRModePtr * modes, int numModes, int numPreferred)
- {
- RRModePtr *newModes;
- int i;
- if (numModes == output->numModes && numPreferred == output->numPreferred) {
- for (i = 0; i < numModes; i++)
- if (output->modes[i] != modes[i])
- break;
- if (i == numModes) {
- for (i = 0; i < numModes; i++)
- RRModeDestroy(modes[i]);
- return TRUE;
- }
- }
- if (numModes) {
- newModes = malloc(numModes * sizeof(RRModePtr));
- if (!newModes)
- return FALSE;
- memcpy(newModes, modes, numModes * sizeof(RRModePtr));
- }
- else
- newModes = NULL;
- if (output->modes) {
- for (i = 0; i < output->numModes; i++)
- RRModeDestroy(output->modes[i]);
- free(output->modes);
- }
- output->modes = newModes;
- output->numModes = numModes;
- output->numPreferred = numPreferred;
- RROutputChanged(output, TRUE);
- return TRUE;
- }
- Bool
- RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
- {
- RRCrtcPtr *newCrtcs;
- int i;
- if (numCrtcs == output->numCrtcs) {
- for (i = 0; i < numCrtcs; i++)
- if (output->crtcs[i] != crtcs[i])
- break;
- if (i == numCrtcs)
- return TRUE;
- }
- if (numCrtcs) {
- newCrtcs = malloc(numCrtcs * sizeof(RRCrtcPtr));
- if (!newCrtcs)
- return FALSE;
- memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr));
- }
- else
- newCrtcs = NULL;
- free(output->crtcs);
- output->crtcs = newCrtcs;
- output->numCrtcs = numCrtcs;
- RROutputChanged(output, TRUE);
- return TRUE;
- }
- void
- RROutputSetCrtc(RROutputPtr output, RRCrtcPtr crtc)
- {
- if (output->crtc == crtc)
- return;
- output->crtc = crtc;
- RROutputChanged(output, FALSE);
- }
- Bool
- RROutputSetConnection(RROutputPtr output, CARD8 connection)
- {
- if (output->connection == connection)
- return TRUE;
- output->connection = connection;
- RROutputChanged(output, TRUE);
- return TRUE;
- }
- Bool
- RROutputSetSubpixelOrder(RROutputPtr output, int subpixelOrder)
- {
- if (output->subpixelOrder == subpixelOrder)
- return TRUE;
- output->subpixelOrder = subpixelOrder;
- RROutputChanged(output, FALSE);
- return TRUE;
- }
- Bool
- RROutputSetPhysicalSize(RROutputPtr output, int mmWidth, int mmHeight)
- {
- if (output->mmWidth == mmWidth && output->mmHeight == mmHeight)
- return TRUE;
- output->mmWidth = mmWidth;
- output->mmHeight = mmHeight;
- RROutputChanged(output, FALSE);
- return TRUE;
- }
- void
- RRDeliverOutputEvent(ClientPtr client, WindowPtr pWin, RROutputPtr output)
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- rrScrPriv(pScreen);
- xRROutputChangeNotifyEvent oe;
- RRCrtcPtr crtc = output->crtc;
- RRModePtr mode = crtc ? crtc->mode : 0;
- oe.type = RRNotify + RREventBase;
- oe.subCode = RRNotify_OutputChange;
- oe.timestamp = pScrPriv->lastSetTime.milliseconds;
- oe.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
- oe.window = pWin->drawable.id;
- oe.output = output->id;
- if (crtc) {
- oe.crtc = crtc->id;
- oe.mode = mode ? mode->mode.id : None;
- oe.rotation = crtc->rotation;
- }
- else {
- oe.crtc = None;
- oe.mode = None;
- oe.rotation = RR_Rotate_0;
- }
- oe.connection = output->connection;
- oe.subpixelOrder = output->subpixelOrder;
- WriteEventsToClient(client, 1, (xEvent *) &oe);
- }
- /*
- * Destroy a Output at shutdown
- */
- void
- RROutputDestroy(RROutputPtr crtc)
- {
- FreeResource(crtc->id, 0);
- }
- static int
- RROutputDestroyResource(pointer value, XID pid)
- {
- RROutputPtr output = (RROutputPtr) value;
- ScreenPtr pScreen = output->pScreen;
- if (pScreen) {
- rrScrPriv(pScreen);
- int i;
- for (i = 0; i < pScrPriv->numOutputs; i++) {
- if (pScrPriv->outputs[i] == output) {
- memmove(pScrPriv->outputs + i, pScrPriv->outputs + i + 1,
- (pScrPriv->numOutputs - (i + 1)) * sizeof(RROutputPtr));
- --pScrPriv->numOutputs;
- break;
- }
- }
- }
- if (output->modes)
- free(output->modes);
- if (output->crtcs)
- free(output->crtcs);
- if (output->clones)
- free(output->clones);
- RRDeleteAllOutputProperties(output);
- free(output);
- return 1;
- }
- /*
- * Initialize output type
- */
- Bool
- RROutputInit(void)
- {
- RROutputType = CreateNewResourceType(RROutputDestroyResource);
- if (!RROutputType)
- return FALSE;
- #ifdef XResExtension
- RegisterResourceName(RROutputType, "OUTPUT");
- #endif
- return TRUE;
- }
- #define OutputInfoExtra (SIZEOF(xRRGetOutputInfoReply) - 32)
- int
- ProcRRGetOutputInfo(ClientPtr client)
- {
- REQUEST(xRRGetOutputInfoReq);;
- xRRGetOutputInfoReply rep;
- RROutputPtr output;
- CARD8 *extra;
- unsigned long extraLen;
- ScreenPtr pScreen;
- rrScrPrivPtr pScrPriv;
- RRCrtc *crtcs;
- RRMode *modes;
- RROutput *clones;
- char *name;
- int i;
- REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
- output = LookupOutput(client, stuff->output, SecurityReadAccess);
- if (!output)
- return RRErrorBase + BadRROutput;
- pScreen = output->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = OutputInfoExtra >> 2;
- rep.timestamp = pScrPriv->lastSetTime.milliseconds;
- rep.crtc = output->crtc ? output->crtc->id : None;
- rep.mmWidth = output->mmWidth;
- rep.mmHeight = output->mmHeight;
- rep.connection = output->connection;
- rep.subpixelOrder = output->subpixelOrder;
- rep.nCrtcs = output->numCrtcs;
- rep.nModes = output->numModes;
- rep.nPreferred = output->numPreferred;
- rep.nClones = output->numClones;
- rep.nameLength = output->nameLength;
- extraLen = ((output->numCrtcs +
- output->numModes +
- output->numClones + ((rep.nameLength + 3) >> 2)) << 2);
- if (extraLen) {
- rep.length += extraLen >> 2;
- extra = malloc(extraLen);
- if (!extra)
- return BadAlloc;
- }
- else
- extra = NULL;
- crtcs = (RRCrtc *) extra;
- modes = (RRMode *) (crtcs + output->numCrtcs);
- clones = (RROutput *) (modes + output->numModes);
- name = (char *) (clones + output->numClones);
- for (i = 0; i < output->numCrtcs; i++) {
- crtcs[i] = output->crtcs[i]->id;
- if (client->swapped)
- swapl(&crtcs[i]);
- }
- for (i = 0; i < output->numModes; i++) {
- modes[i] = output->modes[i]->mode.id;
- if (client->swapped)
- swapl(&modes[i]);
- }
- for (i = 0; i < output->numClones; i++) {
- clones[i] = output->clones[i]->id;
- if (client->swapped)
- swapl(&clones[i]);
- }
- memcpy(name, output->name, output->nameLength);
- if (client->swapped) {
- swaps(&rep.sequenceNumber);
- swapl(&rep.length);
- swapl(&rep.timestamp);
- swapl(&rep.crtc);
- swapl(&rep.mmWidth);
- swapl(&rep.mmHeight);
- swaps(&rep.nCrtcs);
- swaps(&rep.nModes);
- swaps(&rep.nClones);
- swaps(&rep.nameLength);
- }
- WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *) &rep);
- if (extraLen) {
- WriteToClient(client, extraLen, (char *) extra);
- free(extra);
- }
- return client->noClientException;
- }
|