diff options
Diffstat (limited to 'xorg-server/randr/rroutput.c')
-rw-r--r-- | xorg-server/randr/rroutput.c | 1249 |
1 files changed, 624 insertions, 625 deletions
diff --git a/xorg-server/randr/rroutput.c b/xorg-server/randr/rroutput.c index 8f661a383..b57be198f 100644 --- a/xorg-server/randr/rroutput.c +++ b/xorg-server/randr/rroutput.c @@ -1,625 +1,624 @@ -/*
- * Copyright © 2006 Keith Packard
- * Copyright © 2008 Red Hat, 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 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 (ScreenPtr pScreen,
- const char *name,
- int nameLength,
- void *devPrivate)
-{
- RROutputPtr output;
- RROutputPtr *outputs;
- rrScrPrivPtr pScrPriv;
-
- if (!RRInit())
- return NULL;
-
- pScrPriv = rrGetScrPriv(pScreen);
-
- if (pScrPriv->numOutputs)
- outputs = realloc(pScrPriv->outputs,
- (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
- else
- outputs = malloc(sizeof (RROutputPtr));
- if (!outputs)
- return FALSE;
-
- pScrPriv->outputs = outputs;
-
- output = malloc(sizeof (RROutputRec) + nameLength + 1);
- if (!output)
- return NULL;
- output->id = FakeClientID (0);
- output->pScreen = pScreen;
- 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->numUserModes = 0;
- output->userModes = NULL;
- output->properties = NULL;
- output->pendingProperties = FALSE;
- output->changed = FALSE;
- output->devPrivate = devPrivate;
-
- if (!AddResource (output->id, RROutputType, (pointer) output))
- return NULL;
-
- pScrPriv->outputs[pScrPriv->numOutputs++] = output;
- return output;
-}
-
-/*
- * 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;
- }
- else
- newClones = NULL;
- free(output->clones);
- memcpy (newClones, clones, numClones * sizeof (RROutputPtr));
- 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;
- }
- else
- newModes = NULL;
- if (output->modes)
- {
- for (i = 0; i < output->numModes; i++)
- RRModeDestroy (output->modes[i]);
- free(output->modes);
- }
- memcpy (newModes, modes, numModes * sizeof (RRModePtr));
- output->modes = newModes;
- output->numModes = numModes;
- output->numPreferred = numPreferred;
- RROutputChanged (output, TRUE);
- return TRUE;
-}
-
-int
-RROutputAddUserMode (RROutputPtr output,
- RRModePtr mode)
-{
- int m;
- ScreenPtr pScreen = output->pScreen;
- rrScrPriv(pScreen);
- RRModePtr *newModes;
-
- /* Check to see if this mode is already listed for this output */
- for (m = 0; m < output->numModes + output->numUserModes; m++)
- {
- RRModePtr e = (m < output->numModes ?
- output->modes[m] :
- output->userModes[m - output->numModes]);
- if (mode == e)
- return Success;
- }
-
- /* Check with the DDX to see if this mode is OK */
- if (pScrPriv->rrOutputValidateMode)
- if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode))
- return BadMatch;
-
- if (output->userModes)
- newModes = realloc(output->userModes,
- (output->numUserModes + 1) * sizeof (RRModePtr));
- else
- newModes = malloc(sizeof (RRModePtr));
- if (!newModes)
- return BadAlloc;
-
- output->userModes = newModes;
- output->userModes[output->numUserModes++] = mode;
- ++mode->refcnt;
- RROutputChanged (output, TRUE);
- RRTellChanged (pScreen);
- return Success;
-}
-
-int
-RROutputDeleteUserMode (RROutputPtr output,
- RRModePtr mode)
-{
- int m;
-
- /* Find this mode in the user mode list */
- for (m = 0; m < output->numUserModes; m++)
- {
- RRModePtr e = output->userModes[m];
-
- if (mode == e)
- break;
- }
- /* Not there, access error */
- if (m == output->numUserModes)
- return BadAccess;
-
- /* make sure the mode isn't active for this output */
- if (output->crtc && output->crtc->mode == mode)
- return BadMatch;
-
- memmove (output->userModes + m, output->userModes + m + 1,
- (output->numUserModes - m - 1) * sizeof (RRModePtr));
- output->numUserModes--;
- RRModeDestroy (mode);
- return Success;
-}
-
-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;
- }
- else
- newCrtcs = NULL;
- free(output->crtcs);
- memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr));
- output->crtcs = newCrtcs;
- output->numCrtcs = numCrtcs;
- RROutputChanged (output, TRUE);
- return TRUE;
-}
-
-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 output)
-{
- FreeResource (output->id, 0);
-}
-
-static int
-RROutputDestroyResource (pointer value, XID pid)
-{
- RROutputPtr output = (RROutputPtr) value;
- ScreenPtr pScreen = output->pScreen;
- int m;
-
- if (pScreen)
- {
- rrScrPriv(pScreen);
- int i;
-
- if (pScrPriv->primaryOutput == output)
- pScrPriv->primaryOutput = NULL;
-
- 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)
- {
- for (m = 0; m < output->numModes; m++)
- RRModeDestroy (output->modes[m]);
- free(output->modes);
- }
-
- for (m = 0; m < output->numUserModes; m++)
- RRModeDestroy (output->userModes[m]);
- free(output->userModes);
-
- free(output->crtcs);
- free(output->clones);
- RRDeleteAllOutputProperties (output);
- free(output);
- return 1;
-}
-
-/*
- * Initialize output type
- */
-Bool
-RROutputInit (void)
-{
- RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT");
- if (!RROutputType)
- return FALSE;
-
- return TRUE;
-}
-
-/*
- * Initialize output type error value
- */
-void
-RROutputInitErrorValue(void)
-{
- SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput);
-}
-
-#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, n;
-
- REQUEST_SIZE_MATCH(xRRGetOutputInfoReq);
- VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
-
- pScreen = output->pScreen;
- pScrPriv = rrGetScrPriv(pScreen);
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.length = bytes_to_int32(OutputInfoExtra);
- 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 + output->numUserModes;
- rep.nPreferred = output->numPreferred;
- rep.nClones = output->numClones;
- rep.nameLength = output->nameLength;
-
- extraLen = ((output->numCrtcs +
- output->numModes + output->numUserModes +
- output->numClones +
- bytes_to_int32(rep.nameLength)) << 2);
-
- if (extraLen)
- {
- rep.length += bytes_to_int32(extraLen);
- extra = malloc(extraLen);
- if (!extra)
- return BadAlloc;
- }
- else
- extra = NULL;
-
- crtcs = (RRCrtc *) extra;
- modes = (RRMode *) (crtcs + output->numCrtcs);
- clones = (RROutput *) (modes + output->numModes + output->numUserModes);
- name = (char *) (clones + output->numClones);
-
- for (i = 0; i < output->numCrtcs; i++)
- {
- crtcs[i] = output->crtcs[i]->id;
- if (client->swapped)
- swapl (&crtcs[i], n);
- }
- for (i = 0; i < output->numModes + output->numUserModes; i++)
- {
- if (i < output->numModes)
- modes[i] = output->modes[i]->mode.id;
- else
- modes[i] = output->userModes[i - output->numModes]->mode.id;
- if (client->swapped)
- swapl (&modes[i], n);
- }
- for (i = 0; i < output->numClones; i++)
- {
- clones[i] = output->clones[i]->id;
- if (client->swapped)
- swapl (&clones[i], n);
- }
- memcpy (name, output->name, output->nameLength);
- if (client->swapped) {
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.timestamp, n);
- swapl(&rep.crtc, n);
- swapl(&rep.mmWidth, n);
- swapl(&rep.mmHeight, n);
- swaps(&rep.nCrtcs, n);
- swaps(&rep.nModes, n);
- swaps(&rep.nClones, n);
- swaps(&rep.nameLength, n);
- }
- WriteToClient(client, sizeof(xRRGetOutputInfoReply), (char *)&rep);
- if (extraLen)
- {
- WriteToClient (client, extraLen, (char *) extra);
- free(extra);
- }
-
- return Success;
-}
-
-static void
-RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv,
- RROutputPtr output)
-{
- if (pScrPriv->primaryOutput == output)
- return;
-
- /* clear the old primary */
- if (pScrPriv->primaryOutput) {
- RROutputChanged(pScrPriv->primaryOutput, 0);
- pScrPriv->primaryOutput = NULL;
- }
-
- /* set the new primary */
- if (output) {
- pScrPriv->primaryOutput = output;
- RROutputChanged(output, 0);
- }
-
- pScrPriv->layoutChanged = TRUE;
-
- RRTellChanged(pScreen);
-}
-
-int
-ProcRRSetOutputPrimary(ClientPtr client)
-{
- REQUEST(xRRSetOutputPrimaryReq);
- RROutputPtr output = NULL;
- WindowPtr pWin;
- rrScrPrivPtr pScrPriv;
- int rc;
-
- REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq);
-
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- if (stuff->output) {
- VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
-
- if (output->pScreen != pWin->drawable.pScreen) {
- client->errorValue = stuff->window;
- return BadMatch;
- }
- }
-
- pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
- RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output);
-
- return Success;
-}
-
-int
-ProcRRGetOutputPrimary(ClientPtr client)
-{
- REQUEST(xRRGetOutputPrimaryReq);
- WindowPtr pWin;
- rrScrPrivPtr pScrPriv;
- xRRGetOutputPrimaryReply rep;
- RROutputPtr primary = NULL;
- int rc;
-
- REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq);
-
- rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- pScrPriv = rrGetScrPriv(pWin->drawable.pScreen);
- if (pScrPriv)
- primary = pScrPriv->primaryOutput;
-
- memset(&rep, 0, sizeof(rep));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.output = primary ? primary->id : None;
-
- if (client->swapped) {
- int n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.output, n);
- }
-
- WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep);
-
- return Success;
-}
+/* + * Copyright © 2006 Keith Packard + * Copyright © 2008 Red Hat, 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 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 (ScreenPtr pScreen, + const char *name, + int nameLength, + void *devPrivate) +{ + RROutputPtr output; + RROutputPtr *outputs; + rrScrPrivPtr pScrPriv; + + if (!RRInit()) + return NULL; + + pScrPriv = rrGetScrPriv(pScreen); + + if (pScrPriv->numOutputs) + outputs = realloc(pScrPriv->outputs, + (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr)); + else + outputs = malloc(sizeof (RROutputPtr)); + if (!outputs) + return FALSE; + + pScrPriv->outputs = outputs; + + output = malloc(sizeof (RROutputRec) + nameLength + 1); + if (!output) + return NULL; + output->id = FakeClientID (0); + output->pScreen = pScreen; + 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->numUserModes = 0; + output->userModes = NULL; + output->properties = NULL; + output->pendingProperties = FALSE; + output->changed = FALSE; + output->devPrivate = devPrivate; + + if (!AddResource (output->id, RROutputType, (pointer) output)) + return NULL; + + pScrPriv->outputs[pScrPriv->numOutputs++] = output; + return output; +} + +/* + * 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; + } + else + newClones = NULL; + free(output->clones); + memcpy (newClones, clones, numClones * sizeof (RROutputPtr)); + 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; + } + else + newModes = NULL; + if (output->modes) + { + for (i = 0; i < output->numModes; i++) + RRModeDestroy (output->modes[i]); + free(output->modes); + } + memcpy (newModes, modes, numModes * sizeof (RRModePtr)); + output->modes = newModes; + output->numModes = numModes; + output->numPreferred = numPreferred; + RROutputChanged (output, TRUE); + return TRUE; +} + +int +RROutputAddUserMode (RROutputPtr output, + RRModePtr mode) +{ + int m; + ScreenPtr pScreen = output->pScreen; + rrScrPriv(pScreen); + RRModePtr *newModes; + + /* Check to see if this mode is already listed for this output */ + for (m = 0; m < output->numModes + output->numUserModes; m++) + { + RRModePtr e = (m < output->numModes ? + output->modes[m] : + output->userModes[m - output->numModes]); + if (mode == e) + return Success; + } + + /* Check with the DDX to see if this mode is OK */ + if (pScrPriv->rrOutputValidateMode) + if (!pScrPriv->rrOutputValidateMode (pScreen, output, mode)) + return BadMatch; + + if (output->userModes) + newModes = realloc(output->userModes, + (output->numUserModes + 1) * sizeof (RRModePtr)); + else + newModes = malloc(sizeof (RRModePtr)); + if (!newModes) + return BadAlloc; + + output->userModes = newModes; + output->userModes[output->numUserModes++] = mode; + ++mode->refcnt; + RROutputChanged (output, TRUE); + RRTellChanged (pScreen); + return Success; +} + +int +RROutputDeleteUserMode (RROutputPtr output, + RRModePtr mode) +{ + int m; + + /* Find this mode in the user mode list */ + for (m = 0; m < output->numUserModes; m++) + { + RRModePtr e = output->userModes[m]; + + if (mode == e) + break; + } + /* Not there, access error */ + if (m == output->numUserModes) + return BadAccess; + + /* make sure the mode isn't active for this output */ + if (output->crtc && output->crtc->mode == mode) + return BadMatch; + + memmove (output->userModes + m, output->userModes + m + 1, + (output->numUserModes - m - 1) * sizeof (RRModePtr)); + output->numUserModes--; + RRModeDestroy (mode); + return Success; +} + +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; + } + else + newCrtcs = NULL; + free(output->crtcs); + memcpy (newCrtcs, crtcs, numCrtcs * sizeof (RRCrtcPtr)); + output->crtcs = newCrtcs; + output->numCrtcs = numCrtcs; + RROutputChanged (output, TRUE); + return TRUE; +} + +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 output) +{ + FreeResource (output->id, 0); +} + +static int +RROutputDestroyResource (pointer value, XID pid) +{ + RROutputPtr output = (RROutputPtr) value; + ScreenPtr pScreen = output->pScreen; + int m; + + if (pScreen) + { + rrScrPriv(pScreen); + int i; + + if (pScrPriv->primaryOutput == output) + pScrPriv->primaryOutput = NULL; + + 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) + { + for (m = 0; m < output->numModes; m++) + RRModeDestroy (output->modes[m]); + free(output->modes); + } + + for (m = 0; m < output->numUserModes; m++) + RRModeDestroy (output->userModes[m]); + free(output->userModes); + + free(output->crtcs); + free(output->clones); + RRDeleteAllOutputProperties (output); + free(output); + return 1; +} + +/* + * Initialize output type + */ +Bool +RROutputInit (void) +{ + RROutputType = CreateNewResourceType (RROutputDestroyResource, "OUTPUT"); + if (!RROutputType) + return FALSE; + + return TRUE; +} + +/* + * Initialize output type error value + */ +void +RROutputInitErrorValue(void) +{ + SetResourceTypeErrorValue(RROutputType, RRErrorBase + BadRROutput); +} + +#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); + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + + pScreen = output->pScreen; + pScrPriv = rrGetScrPriv(pScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(OutputInfoExtra); + 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 + output->numUserModes; + rep.nPreferred = output->numPreferred; + rep.nClones = output->numClones; + rep.nameLength = output->nameLength; + + extraLen = ((output->numCrtcs + + output->numModes + output->numUserModes + + output->numClones + + bytes_to_int32(rep.nameLength)) << 2); + + if (extraLen) + { + rep.length += bytes_to_int32(extraLen); + extra = malloc(extraLen); + if (!extra) + return BadAlloc; + } + else + extra = NULL; + + crtcs = (RRCrtc *) extra; + modes = (RRMode *) (crtcs + output->numCrtcs); + clones = (RROutput *) (modes + output->numModes + output->numUserModes); + 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 + output->numUserModes; i++) + { + if (i < output->numModes) + modes[i] = output->modes[i]->mode.id; + else + modes[i] = output->userModes[i - output->numModes]->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 Success; +} + +static void +RRSetPrimaryOutput(ScreenPtr pScreen, rrScrPrivPtr pScrPriv, + RROutputPtr output) +{ + if (pScrPriv->primaryOutput == output) + return; + + /* clear the old primary */ + if (pScrPriv->primaryOutput) { + RROutputChanged(pScrPriv->primaryOutput, 0); + pScrPriv->primaryOutput = NULL; + } + + /* set the new primary */ + if (output) { + pScrPriv->primaryOutput = output; + RROutputChanged(output, 0); + } + + pScrPriv->layoutChanged = TRUE; + + RRTellChanged(pScreen); +} + +int +ProcRRSetOutputPrimary(ClientPtr client) +{ + REQUEST(xRRSetOutputPrimaryReq); + RROutputPtr output = NULL; + WindowPtr pWin; + rrScrPrivPtr pScrPriv; + int rc; + + REQUEST_SIZE_MATCH(xRRSetOutputPrimaryReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->output) { + VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess); + + if (output->pScreen != pWin->drawable.pScreen) { + client->errorValue = stuff->window; + return BadMatch; + } + } + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + RRSetPrimaryOutput(pWin->drawable.pScreen, pScrPriv, output); + + return Success; +} + +int +ProcRRGetOutputPrimary(ClientPtr client) +{ + REQUEST(xRRGetOutputPrimaryReq); + WindowPtr pWin; + rrScrPrivPtr pScrPriv; + xRRGetOutputPrimaryReply rep; + RROutputPtr primary = NULL; + int rc; + + REQUEST_SIZE_MATCH(xRRGetOutputPrimaryReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScrPriv = rrGetScrPriv(pWin->drawable.pScreen); + if (pScrPriv) + primary = pScrPriv->primaryOutput; + + memset(&rep, 0, sizeof(rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.output = primary ? primary->id : None; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.output); + } + + WriteToClient(client, sizeof(xRRGetOutputPrimaryReply), &rep); + + return Success; +} |