Add preferred modes for each output. Round vrefresh. Deliver crtc events.

This commit is contained in:
Keith Packard 2006-10-05 22:31:35 -07:00
parent b4659faf9b
commit 1178796a4d
6 changed files with 116 additions and 56 deletions

View File

@ -110,7 +110,7 @@ miRandRInit (ScreenPtr pScreen)
return FALSE; return FALSE;
if (!RROutputSetClones (output, NULL, 0)) if (!RROutputSetClones (output, NULL, 0))
return FALSE; return FALSE;
if (!RROutputSetModes (output, &mode, 1)) if (!RROutputSetModes (output, &mode, 1, 0))
return FALSE; return FALSE;
if (!RROutputSetCrtcs (output, &crtc, 1)) if (!RROutputSetCrtcs (output, &crtc, 1))
return FALSE; return FALSE;

View File

@ -406,9 +406,10 @@ CARD16
RRVerticalRefresh (xRRModeInfo *mode) RRVerticalRefresh (xRRModeInfo *mode)
{ {
CARD32 refresh; CARD32 refresh;
if (!mode->hTotal || !mode->vTotal) CARD32 dots = mode->hTotal * mode->vTotal;
if (!dots)
return 0; return 0;
refresh = mode->dotClock / (mode->hTotal * mode->vTotal); refresh = (mode->dotClock + dots/2) / dots;
if (refresh > 0xffff) if (refresh > 0xffff)
refresh = 0xffff; refresh = 0xffff;
return (CARD16) refresh; return (CARD16) refresh;

View File

@ -80,6 +80,7 @@ struct _rrMode {
char *name; char *name;
void *devPrivate; void *devPrivate;
ScreenPtr screen; ScreenPtr screen;
Bool userDefined;
}; };
struct _rrCrtc { struct _rrCrtc {
@ -114,6 +115,7 @@ struct _rrOutput {
int numClones; int numClones;
RROutputPtr *clones; RROutputPtr *clones;
int numModes; int numModes;
int numPreferred;
RRModePtr *modes; RRModePtr *modes;
Bool changed; Bool changed;
PropertyPtr properties; PropertyPtr properties;
@ -144,6 +146,10 @@ typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr pScreen,
typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen, typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr pScreen,
RRCrtcPtr crtc); RRCrtcPtr crtc);
typedef Bool (*RROutputSetPropertyProcPtr) (ScreenPtr pScreen,
RROutputPtr output,
Atom property);
#endif #endif
typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations); typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@ -187,6 +193,7 @@ typedef struct _rrScrPriv {
RRScreenSetSizeProcPtr rrScreenSetSize; RRScreenSetSizeProcPtr rrScreenSetSize;
RRCrtcSetProcPtr rrCrtcSet; RRCrtcSetProcPtr rrCrtcSet;
RRCrtcSetGammaProcPtr rrCrtcSetGamma; RRCrtcSetGammaProcPtr rrCrtcSetGamma;
RROutputSetPropertyProcPtr rrOutputSetProperty;
#endif #endif
/* /*
@ -589,7 +596,8 @@ RROutputSetClones (RROutputPtr output,
Bool Bool
RROutputSetModes (RROutputPtr output, RROutputSetModes (RROutputPtr output,
RRModePtr *modes, RRModePtr *modes,
int numModes); int numModes,
int numPreferred);
Bool Bool
RROutputSetCrtcs (RROutputPtr output, RROutputSetCrtcs (RROutputPtr output,

View File

@ -88,9 +88,41 @@ RRCrtcNotify (RRCrtcPtr crtc,
ScreenPtr pScreen = crtc->pScreen; ScreenPtr pScreen = crtc->pScreen;
rrScrPriv(pScreen); rrScrPriv(pScreen);
int i, j; int i, j;
int prevNumOutputs = crtc->numOutputs;
if (numOutputs != prevNumOutputs) /*
* Check to see if any of the new outputs were
* not in the old list and mark them as changed
*/
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;
}
}
/*
* Check to see if any of the old outputs are
* not in the new list and mark them as changed
*/
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;
}
}
/*
* Reallocate the crtc output array if necessary
*/
if (numOutputs != crtc->numOutputs)
{ {
RROutputPtr *newoutputs; RROutputPtr *newoutputs;
@ -113,28 +145,13 @@ RRCrtcNotify (RRCrtcPtr crtc,
crtc->outputs = newoutputs; crtc->outputs = newoutputs;
crtc->numOutputs = numOutputs; crtc->numOutputs = numOutputs;
} }
for (i = 0; i < numOutputs; i++) /*
{ * Copy the new list of outputs into the crtc
for (j = 0; j < crtc->numOutputs; j++) */
if (outputs[i] == crtc->outputs[j]) memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
break; /*
if (j != crtc->numOutputs) * Update remaining crtc fields
{ */
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 (mode != crtc->mode)
{ {
if (crtc->mode) if (crtc->mode)
@ -158,6 +175,9 @@ RRCrtcNotify (RRCrtcPtr crtc,
crtc->rotation = rotation; crtc->rotation = rotation;
crtc->changed = TRUE; crtc->changed = TRUE;
} }
/*
* Send events if anything changed
*/
if (crtc->changed) if (crtc->changed)
{ {
if (!pScrPriv->changed) if (!pScrPriv->changed)
@ -170,7 +190,35 @@ RRCrtcNotify (RRCrtcPtr crtc,
void void
RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc) RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
{ {
ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv (pScreen);
xRRCrtcChangeNotifyEvent ce;
RRModePtr mode = crtc->mode;
ce.type = RRNotify + RREventBase;
ce.subCode = RRNotify_CrtcChange;
ce.sequenceNumber = client->sequence;
ce.timestamp = pScrPriv->lastSetTime.milliseconds;
ce.window = pWin->drawable.id;
ce.crtc = crtc->id;
ce.rotation = crtc->rotation;
if (mode)
{
ce.mode = mode->mode.id;
ce.x = crtc->x;
ce.y = crtc->y;
ce.width = mode->mode.width;
ce.height = mode->mode.height;
}
else
{
ce.mode = None;
ce.x = 0;
ce.y = 0;
ce.width = 0;
ce.height = 0;
}
WriteEventsToClient (client, 1, (xEvent *) &ce);
} }
/* /*
@ -381,7 +429,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
rep.y = crtc->y; rep.y = crtc->y;
rep.width = mode ? mode->mode.width : 0; rep.width = mode ? mode->mode.width : 0;
rep.height = mode ? mode->mode.height : 0; rep.height = mode ? mode->mode.height : 0;
rep.mode = mode->mode.id; rep.mode = mode ? mode->mode.id : 0;
rep.rotation = crtc->rotation; rep.rotation = crtc->rotation;
rep.rotations = crtc->rotations; rep.rotations = crtc->rotations;
rep.nOutput = crtc->numOutputs; rep.nOutput = crtc->numOutputs;
@ -572,8 +620,6 @@ ProcRRSetCrtcConfig (ClientPtr client)
goto sendReply; goto sendReply;
} }
if (mode)
{
/* /*
* Validate requested rotation * Validate requested rotation
*/ */
@ -596,6 +642,8 @@ ProcRRSetCrtcConfig (ClientPtr client)
return BadValue; return BadValue;
} }
if (mode)
{
if ((~crtc->rotations) & rotation) if ((~crtc->rotations) & rotation)
{ {
/* /*

View File

@ -41,7 +41,6 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo *b)
if (a->vTotal != b->vTotal) return FALSE; if (a->vTotal != b->vTotal) return FALSE;
if (a->nameLength != b->nameLength) return FALSE; if (a->nameLength != b->nameLength) return FALSE;
if (a->modeFlags != b->modeFlags) return FALSE; if (a->modeFlags != b->modeFlags) return FALSE;
if (a->origin != b->origin) return FALSE;
return TRUE; return TRUE;
} }
@ -75,6 +74,7 @@ RRModeGet (ScreenPtr pScreen,
memcpy (mode->name, name, modeInfo->nameLength); memcpy (mode->name, name, modeInfo->nameLength);
mode->name[modeInfo->nameLength] = '\0'; mode->name[modeInfo->nameLength] = '\0';
mode->screen = pScreen; mode->screen = pScreen;
mode->userDefined = FALSE;
if (pScrPriv->numModes) if (pScrPriv->numModes)
modes = xrealloc (pScrPriv->modes, modes = xrealloc (pScrPriv->modes,
@ -162,7 +162,7 @@ RRModePruneUnused (ScreenPtr pScreen)
memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr)); memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
for (m = 0; m < num; m++) { for (m = 0; m < num; m++) {
mode = unused[m]; mode = unused[m];
if (mode->refcnt == 1 && mode->mode.origin != RRModeOriginUser) if (mode->refcnt == 1 && !mode->userDefined)
FreeResource (mode->mode.id, 0); FreeResource (mode->mode.id, 0);
} }
xfree (unused); xfree (unused);

View File

@ -67,6 +67,7 @@ RROutputCreate (ScreenPtr pScreen,
output->numClones = 0; output->numClones = 0;
output->clones = NULL; output->clones = NULL;
output->numModes = 0; output->numModes = 0;
output->numPreferred = 0;
output->modes = NULL; output->modes = NULL;
output->properties = NULL; output->properties = NULL;
output->changed = TRUE; output->changed = TRUE;
@ -120,12 +121,13 @@ RROutputSetClones (RROutputPtr output,
Bool Bool
RROutputSetModes (RROutputPtr output, RROutputSetModes (RROutputPtr output,
RRModePtr *modes, RRModePtr *modes,
int numModes) int numModes,
int numPreferred)
{ {
RRModePtr *newModes; RRModePtr *newModes;
int i; int i;
if (numModes == output->numModes) if (numModes == output->numModes && numPreferred == output->numPreferred)
{ {
for (i = 0; i < numModes; i++) for (i = 0; i < numModes; i++)
if (output->modes[i] != modes[i]) if (output->modes[i] != modes[i])
@ -155,6 +157,7 @@ RROutputSetModes (RROutputPtr output,
memcpy (newModes, modes, numModes * sizeof (RRModePtr)); memcpy (newModes, modes, numModes * sizeof (RRModePtr));
output->modes = newModes; output->modes = newModes;
output->numModes = numModes; output->numModes = numModes;
output->numPreferred = numPreferred;
output->changed = TRUE; output->changed = TRUE;
return TRUE; return TRUE;
} }
@ -341,10 +344,10 @@ ProcRRGetOutputInfo (ClientPtr client)
rep.subpixelOrder = output->subpixelOrder; rep.subpixelOrder = output->subpixelOrder;
rep.nCrtcs = output->numCrtcs; rep.nCrtcs = output->numCrtcs;
rep.nModes = output->numModes; rep.nModes = output->numModes;
rep.nPreferred = output->numPreferred;
rep.nClones = output->numClones; rep.nClones = output->numClones;
rep.nameLength = output->nameLength; rep.nameLength = output->nameLength;
rep.possibleOptions = output->possibleOptions; rep.possibleOptions = output->possibleOptions;
rep.pad1 = 42;
extraLen = ((output->numCrtcs + extraLen = ((output->numCrtcs +
output->numModes + output->numModes +