RandR: New data structure, old API. At least it compiles now

This commit is contained in:
Keith Packard 2006-07-17 01:21:11 -04:00
parent d95c758630
commit cab3a0145f
3 changed files with 571 additions and 187 deletions

View File

@ -65,11 +65,11 @@ miRRGetInfo (ScreenPtr pScreen, Rotation *rotations)
rrMode.height = pScreen->height; rrMode.height = pScreen->height;
rrMode.widthInMillimeters = pScreen->mmWidth; rrMode.widthInMillimeters = pScreen->mmWidth;
rrMode.heightInMillimeters = pScreen->mmHeight; rrMode.heightInMillimeters = pScreen->mmHeight;
pMonitor = RRRegisterMonitor (pScreen, RR_Rotate_0); rrMode.nameLength = strlen (name);
pMonitor = RRRegisterMonitor (pScreen, NULL, RR_Rotate_0);
pMode = RRRegisterMode (pMonitor, pMode = RRRegisterMode (pMonitor,
&rrMode, &rrMode,
name, name);
strlen (name));
if (!pMode) if (!pMode)
return FALSE; return FALSE;
if (!setConfig) if (!setConfig)
@ -90,6 +90,8 @@ Bool
miRRSetMode (ScreenPtr pScreen, miRRSetMode (ScreenPtr pScreen,
int monitor, int monitor,
RRModePtr pMode, RRModePtr pMode,
int x,
int y,
Rotation rotation) Rotation rotation)
{ {
return TRUE; return TRUE;

View File

@ -163,12 +163,12 @@ RRCloseScreen (int i, ScreenPtr pScreen)
RRMonitorPtr pMonitor; RRMonitorPtr pMonitor;
unwrap (pScrPriv, pScreen, CloseScreen); unwrap (pScrPriv, pScreen, CloseScreen);
while (pMonitor = pScrPriv->pMonitors) while ((pMonitor = pScrPriv->pMonitors))
{ {
RRModePtr pMode; RRModePtr pMode;
pScrPriv->pMonitors = pMonitor->next; pScrPriv->pMonitors = pMonitor->next;
while (pMode = pMonitor->pModes) while ((pMode = pMonitor->pModes))
{ {
pMonitor->pModes = pMode->next; pMonitor->pModes = pMode->next;
xfree (pMode); xfree (pMode);
@ -218,6 +218,20 @@ SRRMonitorChangeNotifyEvent(xRRMonitorChangeNotifyEvent *from,
cpswaps(from->y, to->y); cpswaps(from->y, to->y);
} }
static void
SRRNotifyEvent (xEvent *from,
xEvent *to)
{
switch (from->u.u.detail) {
case RRNotify_MonitorChange:
SRRMonitorChangeNotifyEvent ((xRRMonitorChangeNotifyEvent *) from,
(xRRMonitorChangeNotifyEvent *) to);
break;
default:
break;
}
}
Bool RRScreenInit(ScreenPtr pScreen) Bool RRScreenInit(ScreenPtr pScreen)
{ {
rrScrPrivPtr pScrPriv; rrScrPrivPtr pScrPriv;
@ -336,6 +350,8 @@ RRExtensionInit (void)
RREventBase = extEntry->eventBase; RREventBase = extEntry->eventBase;
EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr) EventSwapVector[RREventBase + RRScreenChangeNotify] = (EventSwapPtr)
SRRScreenChangeNotifyEvent; SRRScreenChangeNotifyEvent;
EventSwapVector[RREventBase + RRNotify] = (EventSwapPtr)
SRRNotifyEvent;
return; return;
} }
@ -349,8 +365,8 @@ TellChanged (WindowPtr pWin, pointer value)
xRRMonitorChangeNotifyEvent me; xRRMonitorChangeNotifyEvent me;
ScreenPtr pScreen = pWin->drawable.pScreen; ScreenPtr pScreen = pWin->drawable.pScreen;
rrScrPriv(pScreen); rrScrPriv(pScreen);
RRMonitorPtr pMonitor = pScrPriv->pMonitors;
RRModePtr pMode; RRModePtr pMode;
RRMonitorPtr pMonitor;
WindowPtr pRoot = WindowTable[pScreen->myNum]; WindowPtr pRoot = WindowTable[pScreen->myNum];
int i; int i;
@ -364,7 +380,7 @@ TellChanged (WindowPtr pWin, pointer value)
if (client == serverClient || client->clientGone) if (client == serverClient || client->clientGone)
continue; continue;
if (pRREvent->mask & RRMonitorChangeNotifyMask)) if (pRREvent->mask & RRMonitorChangeNotifyMask)
{ {
me.type = RRNotify + RREventBase; me.type = RRNotify + RREventBase;
me.subCode = RRNotify_MonitorChange; me.subCode = RRNotify_MonitorChange;
@ -377,12 +393,13 @@ TellChanged (WindowPtr pWin, pointer value)
#else #else
me.subpixelOrder = SubPixelUnknown; me.subpixelOrder = SubPixelUnknown;
#endif #endif
for (i = 0; i < pScrPriv->nMonitors; i++) for (pMonitor = pScrPriv->pMonitors, i = 0;
pMonitor;
pMonitor = pMonitor->next, i++)
{ {
pMonitor = &pScrPriv->pMonitors[i];
me.monitor = i; me.monitor = i;
if (pMonitor->mode >= 0) { if (pMonitor->pMode) {
me.modeID = pMonitor->pMode[pMonitor->mode].id; me.modeID = pMonitor->pMode->id;
me.rotation = pMonitor->rotation; me.rotation = pMonitor->rotation;
me.x = pMonitor->x; me.x = pMonitor->x;
me.y = pMonitor->y; me.y = pMonitor->y;
@ -396,10 +413,10 @@ TellChanged (WindowPtr pWin, pointer value)
} }
} }
if ((pRREvent->mask & RRScreenChangeNotifyMask) && if ((pRREvent->mask & RRScreenChangeNotifyMask) &&
pScrPriv->nMonitors > 0) (pMonitor = pScrPriv->pMonitors))
{ {
se.type = RRScreenChangeNotify + RREventBase; se.type = RRScreenChangeNotify + RREventBase;
se.rotation = (CARD8) pScrPriv->rotation; se.rotation = (CARD8) pMonitor->rotation;
se.timestamp = pScrPriv->lastSetTime.milliseconds; se.timestamp = pScrPriv->lastSetTime.milliseconds;
se.sequenceNumber = client->sequence; se.sequenceNumber = client->sequence;
se.configTimestamp = pScrPriv->lastConfigTime.milliseconds; se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
@ -413,14 +430,14 @@ TellChanged (WindowPtr pWin, pointer value)
pMonitor = &pScrPriv->pMonitors[0]; pMonitor = &pScrPriv->pMonitors[0];
se.sequenceNumber = client->sequence; se.sequenceNumber = client->sequence;
if (pMonitor->mode >= 0) if (pMonitor->pMode)
{ {
pMode = &pMonitor->pModes[pMonitor->mode]; pMode = pMonitor->pMode;
se.sizeID = pMode->id; se.sizeID = pMode->id;
se.widthInPixels = pMode->width; se.widthInPixels = pMode->mode.width;
se.heightInPixels = pMode->height; se.heightInPixels = pMode->mode.height;
se.widthInMillimeters = pMode->mmWidth; se.widthInMillimeters = pMode->mode.widthInMillimeters;
se.heightInMillimeters = pMode->mmHeight; se.heightInMillimeters = pMode->mode.heightInMillimeters;
} }
else else
{ {
@ -440,70 +457,107 @@ TellChanged (WindowPtr pWin, pointer value)
return WT_WALKCHILDREN; return WT_WALKCHILDREN;
} }
static void
RRFreeMode (RRModePtr pMode)
{
xfree (pMode);
}
static void
RRFreeModes (RRModePtr pHead)
{
RRModePtr pMode;
while ((pMode = pHead))
{
pHead = pMode->next;
RRFreeMode (pMode);
}
}
static void
RRFreeMonitor (RRMonitorPtr pMonitor)
{
RRFreeModes (pMonitor->pModes);
xfree (pMonitor);
}
static Bool static Bool
RRGetInfo (ScreenPtr pScreen) RRGetInfo (ScreenPtr pScreen)
{ {
rrScrPriv (pScreen); rrScrPriv (pScreen);
int m, s, n;
Bool changed; Bool changed;
Rotation rotations; Rotation rotations;
RRMonitorPtr pMonitor; RRMonitorPtr pMonitor, *pPrevMon;
RRModePtr pMode; RRModePtr pMode, *pPrevMode;
int monitorid;
for (m = 0; m < pScrPriv->nMonitors; m++) for (pMonitor = pScrPriv->pMonitors; pMonitor; pMonitor = pMonitor->next)
{ {
pMonitor = &pScrPriv->pMonitors[m]; pMonitor->oldReferenced = TRUE;
pMonitor->oldReferenced = pMonitor->referenced;
pMonitor->referenced = FALSE; pMonitor->referenced = FALSE;
for (s = 0; s < pMonitor->nModes; s++) pMonitor->pMode = NULL;
for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
{ {
pMode = &pSize->pModes[s]; pMode->oldReferenced = TRUE;
pMode->oldReferenced = pMode->referenced;
pMode->referenced = FALSE; pMode->referenced = FALSE;
} }
} }
changed = FALSE;
rotations = 0; rotations = 0;
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
return FALSE; return FALSE;
changed = FALSE;
/* Old GetInfo clients return rotations here */ /* Old GetInfo clients return rotations here */
if (rotations && pScrPriv->nMonitors) { if (rotations && pScrPriv->pMonitors) {
/* /*
* Check whether anything changed and simultaneously generate * Check whether anything changed and simultaneously generate
* the protocol id values for the objects * the protocol id values for the objects
*/ */
if (rotations != pScrPriv->pMonitors[i].rotations) if (rotations != pScrPriv->pMonitors->rotations)
{ {
pScrPriv->pMonitors[i].rotations = rotations; pScrPriv->pMonitors->rotations = rotations;
changed = TRUE; changed = TRUE;
} }
} }
n = 0; /*
for (m = 0; m < pScrPriv->nMonitors; m++) * Walk monitor and mode lists looking for updates
*/
monitorid = 0;
for (pPrevMon = &pScrPriv->pMonitors; (pMonitor = *pPrevMon);)
{ {
int modeid = 0; int modeid = 0;
pMonitor = &pScrPriv->pMonitors[m];
if (pMonitor->oldReferenced != pMonitor->referenced)
changed = TRUE;
if (pMonitor->referenced) if (pMonitor->referenced)
{ {
for (s = 0; s < pMonitor->nModes; s++) pMonitor->id = monitorid++;
{ if (!pMonitor->oldReferenced)
pMode = &pMonitor->pModes[s];
if (pMode->oldReferenced != pMode->referenced)
changed = TRUE; changed = TRUE;
for (pPrevMode = &pMonitor->pModes; (pMode = *pPrevMode);)
{
if (pMode->referenced) if (pMode->referenced)
{
pMode->id = modeid++; pMode->id = modeid++;
if (!pMode->oldReferenced)
changed = TRUE;
} }
n++; else
{
*pPrevMode = pMode->next;
changed = TRUE;
RRFreeMode (pMode);
}
}
}
else
{
*pPrevMon = pMonitor->next;
changed = TRUE;
RRFreeMonitor (pMonitor);
} }
pMonitor->nModesInUse = modeid;
} }
pScrPriv->nMonitorsInUse = n;
if (changed) if (changed)
{ {
UpdateCurrentTime (); UpdateCurrentTime ();
@ -548,6 +602,10 @@ ProcRRQueryVersion (ClientPtr client)
rep.type = X_Reply; rep.type = X_Reply;
rep.length = 0; rep.length = 0;
rep.sequenceNumber = client->sequence; rep.sequenceNumber = client->sequence;
/*
* Report the current version; the current
* spec says they're all compatible after 1.0
*/
rep.majorVersion = RANDR_MAJOR; rep.majorVersion = RANDR_MAJOR;
rep.minorVersion = RANDR_MINOR; rep.minorVersion = RANDR_MINOR;
if (client->swapped) { if (client->swapped) {
@ -604,6 +662,100 @@ RREditConnectionInfo (ScreenPtr pScreen)
root->mmHeight = pScreen->mmHeight; root->mmHeight = pScreen->mmHeight;
} }
static int
RRNumModes (RRMonitorPtr pMonitor)
{
int n = 0;
RRModePtr pMode;
for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
n++;
return n;
}
typedef struct _RR10Data {
RRScreenSizePtr sizes;
int nsize;
int nrefresh;
int size;
CARD16 refresh;
} RR10DataRec, *RR10DataPtr;
static CARD16
RRVerticalRefresh (xRRMonitorMode *mode)
{
CARD32 refresh;
if (!mode->hTotal || !mode->vTotal)
return 0;
refresh = mode->dotClock / (mode->hTotal * mode->vTotal);
if (refresh > 0xffff)
refresh = 0xffff;
return (CARD16) refresh;
}
/*
* Convert 1.2 monitor data into 1.0 screen data
*/
static RR10DataPtr
RR10GetData (ScreenPtr pScreen, RRMonitorPtr pMonitor)
{
RR10DataPtr data;
RRScreenSizePtr size;
int nmode = RRNumModes (pMonitor);
int i;
int j;
RRRefreshPtr refresh;
CARD16 vRefresh;
RRModePtr pMode;
/* Make sure there is plenty of space for any combination */
data = malloc (sizeof (RR10DataRec) +
sizeof (RRScreenSizeRec) * nmode +
sizeof (RRRefreshRec) * nmode);
if (!data)
return NULL;
size = (RRScreenSizePtr) (data + 1);
refresh = (RRRefreshPtr) (size + nmode);
data->nsize = 0;
data->nrefresh = 0;
data->size = 0;
data->refresh = 0;
for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
{
for (i = 0; i < data->nsize; i++)
if (pMode->mode.width == size[i].width &&
pMode->mode.height == size[i].height)
break;
if (i == data->nsize)
{
size[i].width = pMode->mode.width;
size[i].height = pMode->mode.height;
size[i].mmWidth = pMode->mode.widthInMillimeters;
size[i].mmHeight = pMode->mode.heightInMillimeters;
size[i].nrefresh = 0;
size[i].refresh = &refresh[data->nrefresh];
data->nsize++;
}
vRefresh = RRVerticalRefresh (&pMode->mode);
for (j = 0; j < size[i].nrefresh; j++)
if (vRefresh == size[i].refresh[j].refresh)
break;
if (j == size[i].nrefresh)
{
size[i].refresh[j].refresh = vRefresh;
size[i].refresh[j].pMode = pMode;
size[i].nrefresh++;
data->nrefresh++;
}
if (pMode == pMonitor->pMode)
{
data->size = i;
data->refresh = vRefresh;
}
}
return data;
}
static int static int
ProcRRGetScreenInfo (ClientPtr client) ProcRRGetScreenInfo (ClientPtr client)
{ {
@ -626,7 +778,11 @@ ProcRRGetScreenInfo (ClientPtr client)
pScreen = pWin->drawable.pScreen; pScreen = pWin->drawable.pScreen;
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
rep.pad = 0; rep.pad = 0;
if (!pScrPriv)
if (pScrPriv)
RRGetInfo (pScreen);
if (!pScrPriv && !pScrPriv->pMonitors)
{ {
rep.type = X_Reply; rep.type = X_Reply;
rep.setOfRotations = RR_Rotate_0;; rep.setOfRotations = RR_Rotate_0;;
@ -645,58 +801,49 @@ ProcRRGetScreenInfo (ClientPtr client)
} }
else else
{ {
RRMonitorPtr pMonitor = pScrPriv->pMonitors;
int i, j; int i, j;
xScreenSizes *size; xScreenSizes *size;
CARD16 *rates; CARD16 *rates;
CARD8 *data8; CARD8 *data8;
Bool has_rate = RRClientKnowsRates (client); Bool has_rate = RRClientKnowsRates (client);
RR10DataPtr pData;
RRScreenSizePtr pSize;
RRGetInfo (pScreen); pData = RR10GetData (pScreen, pMonitor);
if (!pData)
return BadAlloc;
rep.type = X_Reply; rep.type = X_Reply;
rep.setOfRotations = pScrPriv->rotations; rep.setOfRotations = pMonitor->rotations;
rep.sequenceNumber = client->sequence; rep.sequenceNumber = client->sequence;
rep.length = 0; rep.length = 0;
rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id; rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
rep.timestamp = pScrPriv->lastSetTime.milliseconds; rep.timestamp = pScrPriv->lastSetTime.milliseconds;
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.rotation = pScrPriv->rotation; rep.rotation = pMonitor->rotation;
rep.nSizes = pScrPriv->nSizesInUse; rep.nSizes = pData->nsize;
rep.rate = pScrPriv->rate; rep.nrateEnts = pData->nrefresh;
rep.nrateEnts = 0; rep.sizeID = pData->size;
if (has_rate) rep.rate = pData->refresh;
{
for (i = 0; i < pScrPriv->nSizes; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{
rep.nrateEnts += (1 + pSize->nRatesInUse);
}
}
}
if (pScrPriv->size >= 0)
rep.sizeID = pScrPriv->pSizes[pScrPriv->size].id;
else
return BadImplementation;
extraLen = (rep.nSizes * sizeof (xScreenSizes) + extraLen = (rep.nSizes * sizeof (xScreenSizes) +
rep.nrateEnts * sizeof (CARD16)); rep.nrateEnts * sizeof (CARD16));
extra = (CARD8 *) xalloc (extraLen); extra = (CARD8 *) xalloc (extraLen);
if (!extra) if (!extra)
{
xfree (pData);
return BadAlloc; return BadAlloc;
}
/* /*
* First comes the size information * First comes the size information
*/ */
size = (xScreenSizes *) extra; size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes); rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pScrPriv->nSizes; i++) for (i = 0; i < pData->nsize; i++)
{
RRScreenSizePtr pSize = &pScrPriv->pSizes[i];
if (pSize->referenced)
{ {
pSize = &pData->sizes[i];
size->widthInPixels = pSize->width; size->widthInPixels = pSize->width;
size->heightInPixels = pSize->height; size->heightInPixels = pSize->height;
size->widthInMillimeters = pSize->mmWidth; size->widthInMillimeters = pSize->mmWidth;
@ -711,18 +858,15 @@ ProcRRGetScreenInfo (ClientPtr client)
size++; size++;
if (has_rate) if (has_rate)
{ {
*rates = pSize->nRatesInUse; *rates = pSize->nrefresh;
if (client->swapped) if (client->swapped)
{ {
swaps (rates, n); swaps (rates, n);
} }
rates++; rates++;
for (j = 0; j < pSize->nRates; j++) for (j = 0; j < pSize->nrefresh; j++)
{ {
RRScreenRatePtr pRate = &pSize->pRates[j]; *rates = pSize->refresh[j].refresh;
if (pRate->referenced)
{
*rates = pRate->rate;
if (client->swapped) if (client->swapped)
{ {
swaps (rates, n); swaps (rates, n);
@ -731,8 +875,8 @@ ProcRRGetScreenInfo (ClientPtr client)
} }
} }
} }
} xfree (pData);
}
data8 = (CARD8 *) rates; data8 = (CARD8 *) rates;
if (data8 - (CARD8 *) extra != extraLen) if (data8 - (CARD8 *) extra != extraLen)
@ -770,12 +914,15 @@ ProcRRSetScreenConfig (ClientPtr client)
rrScrPrivPtr pScrPriv; rrScrPrivPtr pScrPriv;
TimeStamp configTime; TimeStamp configTime;
TimeStamp time; TimeStamp time;
RRScreenSizePtr pSize;
int i; int i;
Rotation rotation; Rotation rotation;
int rate; int rate;
short oldWidth, oldHeight; short oldWidth, oldHeight;
Bool has_rate; Bool has_rate;
RRMonitorPtr pMonitor;
RRModePtr pMode;
RR10DataPtr pData = NULL;
RRScreenSizePtr pSize;
UpdateCurrentTime (); UpdateCurrentTime ();
@ -812,6 +959,14 @@ ProcRRSetScreenConfig (ClientPtr client)
if (!RRGetInfo (pScreen)) if (!RRGetInfo (pScreen))
return BadAlloc; return BadAlloc;
pMonitor = pScrPriv->pMonitors;
if (!pMonitor)
{
time = currentTime;
rep.status = RRSetConfigFailed;
goto sendReply;
}
/* /*
* if the client's config timestamp is not the same as the last config * if the client's config timestamp is not the same as the last config
* timestamp, then the config information isn't up-to-date and * timestamp, then the config information isn't up-to-date and
@ -823,26 +978,20 @@ ProcRRSetScreenConfig (ClientPtr client)
goto sendReply; goto sendReply;
} }
/* pData = RR10GetData (pScreen, pMonitor);
* Search for the requested size if (!pData)
*/ return BadAlloc;
pSize = 0;
for (i = 0; i < pScrPriv->nSizes; i++) if (stuff->sizeID >= pData->nsize)
{
pSize = &pScrPriv->pSizes[i];
if (pSize->referenced && pSize->id == stuff->sizeID)
{
break;
}
}
if (i == pScrPriv->nSizes)
{ {
/* /*
* Invalid size ID * Invalid size ID
*/ */
client->errorValue = stuff->sizeID; client->errorValue = stuff->sizeID;
xfree (pData);
return BadValue; return BadValue;
} }
pSize = &pData->sizes[stuff->sizeID];
/* /*
* Validate requested rotation * Validate requested rotation
@ -861,15 +1010,17 @@ ProcRRSetScreenConfig (ClientPtr client)
* Invalid rotation * Invalid rotation
*/ */
client->errorValue = stuff->rotation; client->errorValue = stuff->rotation;
xfree (pData);
return BadValue; return BadValue;
} }
if ((~pScrPriv->rotations) & rotation) if ((~pMonitor->rotations) & rotation)
{ {
/* /*
* requested rotation or reflection not supported by screen * requested rotation or reflection not supported by screen
*/ */
client->errorValue = stuff->rotation; client->errorValue = stuff->rotation;
xfree (pData);
return BadMatch; return BadMatch;
} }
@ -883,21 +1034,24 @@ ProcRRSetScreenConfig (ClientPtr client)
if (rate) if (rate)
{ {
for (i = 0; i < pSize->nRates; i++) for (i = 0; i < pSize->nrefresh; i++)
{ {
RRScreenRatePtr pRate = &pSize->pRates[i]; if (pSize->refresh[i].refresh == rate)
if (pRate->referenced && pRate->rate == rate)
break; break;
} }
if (i == pSize->nRates) if (i == pSize->nrefresh)
{ {
/* /*
* Invalid rate * Invalid rate
*/ */
client->errorValue = rate; client->errorValue = rate;
xfree (pData);
return BadValue; return BadValue;
} }
pMode = pSize->refresh[i].pMode;
} }
else
pMode = pSize->refresh[0].pMode;
/* /*
* Make sure the requested set-time is not older than * Make sure the requested set-time is not older than
@ -912,9 +1066,51 @@ ProcRRSetScreenConfig (ClientPtr client)
/* /*
* call out to ddx routine to effect the change * call out to ddx routine to effect the change
*/ */
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, if (pScrPriv->rrSetScreenSize && pScrPriv->rrSetMode)
pSize))
{ {
xScreenSizes oldSize;
if (!(*pScrPriv->rrSetMode) (pScreen, 0, NULL, 0, 0, RR_Rotate_0))
goto fail;
oldSize.widthInPixels = pScreen->width;
oldSize.heightInPixels = pScreen->width;
oldSize.widthInMillimeters = pScreen->mmWidth;
oldSize.heightInMillimeters = pScreen->mmHeight;
if (!(*pScrPriv->rrSetScreenSize) (pScreen,
pMode->mode.width,
pMode->mode.height,
pMode->mode.widthInMillimeters,
pMode->mode.heightInMillimeters))
{
(void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
pMonitor->x, pMonitor->y,
pMonitor->rotation);
goto fail;
}
if (!(*pScrPriv->rrSetMode) (pScreen, 0, pMode, 0, 0, rotation))
{
(void) (*pScrPriv->rrSetScreenSize) (pScreen,
oldSize.widthInPixels,
oldSize.heightInPixels,
oldSize.widthInMillimeters,
oldSize.heightInMillimeters);
(void) (*pScrPriv->rrSetMode) (pScreen, 0, pMonitor->pMode,
pMonitor->x, pMonitor->y,
pMonitor->rotation);
goto fail;
}
}
#ifdef RANDR_SCREEN_INTERFACE
else if (pScrPriv->rrSetConfig)
{
if (!(*pScrPriv->rrSetConfig) (pScreen, rotation, rate, pSize))
{
goto fail;
}
}
#endif
else
{
fail: ;
/* /*
* unknown DDX failure, report to client * unknown DDX failure, report to client
*/ */
@ -925,7 +1121,7 @@ ProcRRSetScreenConfig (ClientPtr client)
/* /*
* set current extension configuration pointers * set current extension configuration pointers
*/ */
RRSetCurrentConfig (pScreen, rotation, rate, pSize); RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
/* /*
* Deliver ScreenChangeNotify events whenever * Deliver ScreenChangeNotify events whenever
@ -954,6 +1150,9 @@ ProcRRSetScreenConfig (ClientPtr client)
sendReply: sendReply:
if (pData)
xfree (pData);
rep.type = X_Reply; rep.type = X_Reply;
/* rep.status has already been filled in */ /* rep.status has already been filled in */
rep.length = 0; rep.length = 0;
@ -1055,7 +1254,7 @@ RRSetScreenConfig (ScreenPtr pScreen,
/* /*
* set current extension configuration pointers * set current extension configuration pointers
*/ */
RRSetCurrentConfig (pScreen, rotation, rate, pSize); RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
/* /*
* Deliver ScreenChangeNotify events whenever * Deliver ScreenChangeNotify events whenever
@ -1075,7 +1274,6 @@ RRSetScreenConfig (ScreenPtr pScreen,
* Fix pointer bounds and location * Fix pointer bounds and location
*/ */
ScreenRestructured (pScreen); ScreenRestructured (pScreen);
return Success; return Success;
} }
@ -1286,21 +1484,113 @@ SProcRRDispatch (ClientPtr client)
} }
} }
/*
static Bool * Register a monitor for a screen. identifier is a unique identifier
RRScreenSizeMatches (RRScreenSizePtr a, * for the monitors of a particular screen.
RRScreenSizePtr b) */
RRMonitorPtr
RRRegisterMonitor (ScreenPtr pScreen,
void *identifier,
Rotation rotations)
{ {
if (a->width != b->width) rrScrPriv (pScreen);
return FALSE; RRMonitorPtr pMonitor, *pPrev, *pInsert;
if (a->height != b->height)
return FALSE; pInsert = NULL;
if (a->mmWidth != b->mmWidth) for (pPrev = &pScrPriv->pMonitors; (pMonitor = *pPrev);
return FALSE; pPrev = &(pMonitor)->next)
if (a->mmHeight != b->mmHeight) {
return FALSE; if (pMonitor->identifier == identifier)
return TRUE; {
pMonitor->referenced = TRUE;
return pMonitor;
} }
if (!pMonitor->referenced)
pInsert = pPrev;
}
if (!pInsert)
pInsert = pPrev;
/*
* New monitor, add before the first unreferenced monitor
*/
pMonitor = xalloc (sizeof (RRMonitor));
if (!pMonitor)
return NULL;
pMonitor->pScreen = pScreen;
pMonitor->pModes = NULL;
pMonitor->identifier = identifier;
pMonitor->referenced = TRUE;
pMonitor->oldReferenced = FALSE;
pMonitor->rotations = RR_Rotate_0;
pMonitor->pMode = NULL;
pMonitor->x = 0;
pMonitor->y = 0;
pMonitor->rotation = RR_Rotate_0;
pMonitor->next = *pInsert;
*pInsert = pMonitor;
return pMonitor;
}
/*
* Register a mode for a monitor
*/
RRModePtr
RRRegisterMode (RRMonitorPtr pMonitor,
xRRMonitorMode *pModeline,
char *name)
{
RRModePtr pMode, *pPrev, *pInsert = NULL;
/*
* Find existing mode with same modeline and name
*/
for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
{
if (!memcmp (&pMode->mode, pModeline, sizeof (xRRMonitorMode)) &&
pMode->mode.nameLength == pModeline->nameLength &&
!memcmp (RRModeName(pMode), name, pModeline->nameLength))
{
pMode->referenced = TRUE;
return pMode;
}
if (!pMode->referenced)
pInsert = pPrev;
}
if (!pInsert)
pInsert = pPrev;
/*
* Create a new mode, inserting before the first unreferenced mode
*/
pMode = xalloc (sizeof (RRMode) + pModeline->nameLength + 1);
pMode->referenced = TRUE;
pMode->oldReferenced = FALSE;
pMode->mode = *pModeline;
memcpy (RRModeName (pMode), name, pModeline->nameLength);
RRModeName(pMode)[pModeline->nameLength] = '\0';
pMode->next = *pInsert;
*pInsert = pMode;
return pMode;
}
void
RRSetCurrentMode (RRMonitorPtr pMonitor,
RRModePtr pMode,
int x,
int y,
Rotation rotation)
{
pMonitor->pMode = pMode;
pMonitor->x = x;
pMonitor->y = y;
pMonitor->rotation = rotation;
}
#ifdef RANDR_SCREEN_INTERFACE
RRScreenSizePtr RRScreenSizePtr
RRRegisterSize (ScreenPtr pScreen, RRRegisterSize (ScreenPtr pScreen,
@ -1310,36 +1600,45 @@ RRRegisterSize (ScreenPtr pScreen,
short mmHeight) short mmHeight)
{ {
rrScrPriv (pScreen); rrScrPriv (pScreen);
int i; xRRMonitorMode tmp;
RRScreenSize tmp; RRMonitorPtr pMonitor;
RRScreenSizePtr pNew; RRModePtr pMode, *pPrev;
char name[100];
if (!pScrPriv) if (!pScrPriv)
return 0; return NULL;
pMonitor = pScrPriv->pMonitors;
if (!pMonitor)
return NULL;
tmp.id = -1; for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &(pMode->next))
if (pMode->mode.width == width &&
pMode->mode.height == height &&
pMode->mode.widthInMillimeters == mmWidth &&
pMode->mode.heightInMillimeters == mmHeight)
{
pMode->referenced =TRUE;
return (void *) pMode;
}
memset (&tmp, '\0', sizeof (xRRMonitorMode));
memset (name, '\0', sizeof (name));
sprintf (name, "%dx%d", width, height);
tmp.width = width; tmp.width = width;
tmp.height= height; tmp.height= height;
tmp.mmWidth = mmWidth; tmp.widthInMillimeters = mmWidth;
tmp.mmHeight = mmHeight; tmp.heightInMillimeters = mmHeight;
tmp.pRates = 0; tmp.nameLength = strlen (name) + 10; /* leave space for refresh */
tmp.nRates = 0; pMode = RRRegisterMode (pMonitor, &tmp, name);
tmp.nRatesInUse = 0; return (void *) pMode;
tmp.referenced = TRUE;
tmp.oldReferenced = FALSE;
for (i = 0; i < pScrPriv->nSizes; i++)
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
{
pScrPriv->pSizes[i].referenced = TRUE;
return &pScrPriv->pSizes[i];
} }
pNew = xrealloc (pScrPriv->pSizes,
(pScrPriv->nSizes + 1) * sizeof (RRScreenSize)); static Bool
if (!pNew) RRModesMatchSize (RRModePtr a, RRModePtr b)
return 0; {
pNew[pScrPriv->nSizes++] = tmp; return (a->mode.width == a->mode.width &&
pScrPriv->pSizes = pNew; a->mode.height == b->mode.height &&
return &pNew[pScrPriv->nSizes-1]; a->mode.widthInMillimeters == b->mode.widthInMillimeters &&
a->mode.heightInMillimeters == b->mode.heightInMillimeters);
} }
Bool RRRegisterRate (ScreenPtr pScreen, Bool RRRegisterRate (ScreenPtr pScreen,
@ -1347,31 +1646,61 @@ Bool RRRegisterRate (ScreenPtr pScreen,
int rate) int rate)
{ {
rrScrPriv(pScreen); rrScrPriv(pScreen);
int i; RRMonitorPtr pMonitor;
RRScreenRatePtr pNew, pRate; RRModePtr pSizeMode = (RRModePtr) pSize;
RRModePtr pMode, *pPrev;
CARD16 width = pSizeMode->mode.width;
CARD16 height = pSizeMode->mode.height;
char name[100];
xRRMonitorMode modeLine;
if (!pScrPriv) if (!pScrPriv)
return FALSE; return FALSE;
for (i = 0; i < pSize->nRates; i++) pMonitor = pScrPriv->pMonitors;
if (!pMonitor)
return FALSE;
for (pPrev = &pMonitor->pModes; (pMode = *pPrev); pPrev = &pMode->next)
{ {
pRate = &pSize->pRates[i]; if (RRModesMatchSize (pMode, pSizeMode))
if (pRate->rate == rate)
{ {
pRate->referenced = TRUE; if (pMode->mode.dotClock == 0)
{
/*
* First refresh for this size; reprogram this mode
* with the right refresh.
*/
pMode->mode.hSyncStart = width;
pMode->mode.hSyncEnd = width;
pMode->mode.hTotal = width;
pMode->mode.hSkew = 0;
pMode->mode.vSyncStart = height;
pMode->mode.vSyncEnd = height;
pMode->mode.vTotal = height;
pMode->mode.dotClock = width * height * rate;
sprintf ((char *) (pMode + 1), "%dx%d@%d", width, height, rate);
pMode->mode.modeFlags = 0;
pMode->mode.nameLength = strlen ((char *) (pMode + 1));
pMode->referenced = TRUE;
return TRUE;
}
else if (rate == RRVerticalRefresh (&pMode->mode))
{
pMode->referenced = TRUE;
return TRUE; return TRUE;
} }
} }
}
pNew = xrealloc (pSize->pRates, sprintf (name, "%dx%d@%d", pSizeMode->mode.width, pSizeMode->mode.height,
(pSize->nRates + 1) * sizeof (RRScreenRate)); rate);
if (!pNew) modeLine = pSizeMode->mode;
modeLine.dotClock = rate * modeLine.vTotal * modeLine.hTotal;
modeLine.nameLength = strlen (name);
pMode = RRRegisterMode (pMonitor, &modeLine, name);
if (!pMode)
return FALSE; return FALSE;
pRate = &pNew[pSize->nRates++];
pRate->rate = rate;
pRate->referenced = TRUE;
pRate->oldReferenced = FALSE;
pSize->pRates = pNew;
return TRUE; return TRUE;
} }
@ -1379,11 +1708,15 @@ Rotation
RRGetRotation(ScreenPtr pScreen) RRGetRotation(ScreenPtr pScreen)
{ {
rrScrPriv (pScreen); rrScrPriv (pScreen);
RRMonitorPtr pMonitor;
if (!pScrPriv) if (!pScrPriv)
return RR_Rotate_0; return RR_Rotate_0;
return pScrPriv->rotation; pMonitor = pScrPriv->pMonitors;
if (!pMonitor)
return RR_Rotate_0;
return pMonitor->rotation;
} }
void void
@ -1393,11 +1726,25 @@ RRSetCurrentConfig (ScreenPtr pScreen,
RRScreenSizePtr pSize) RRScreenSizePtr pSize)
{ {
rrScrPriv (pScreen); rrScrPriv (pScreen);
RRMonitorPtr pMonitor;
RRModePtr pMode;
RRModePtr pSizeMode = (RRModePtr) pSize;
if (!pScrPriv) if (!pScrPriv)
return; return;
pMonitor = pScrPriv->pMonitors;
if (!pMonitor)
return;
pScrPriv->rotation = rotation; for (pMode = pMonitor->pModes; pMode; pMode = pMode->next)
pScrPriv->size = pSize - pScrPriv->pSizes; {
pScrPriv->rate = rate; if (RRModesMatchSize (pMode, pSizeMode) &&
RRVerticalRefresh (&pMode->mode) == rate)
break;
} }
if (!pMode)
return;
RRSetCurrentMode (pMonitor, pMode, 0, 0, rotation);
}
#endif

View File

@ -34,11 +34,19 @@
#include <X11/extensions/randrproto.h> #include <X11/extensions/randrproto.h>
#define RANDR_SCREEN_INTERFACE 1
/*
* Modeline for a monitor. Name follows directly after this struct
*/
#define RRModeName(pMode) ((char *) (pMode + 1))
typedef struct _rrMode { typedef struct _rrMode {
struct _rrMode *next; struct _rrMode *next;
int id;
Bool referenced; Bool referenced;
Bool oldReferenced; Bool oldReferenced;
int id;
xRRMonitorMode mode; xRRMonitorMode mode;
} RRMode, *RRModePtr; } RRMode, *RRModePtr;
@ -47,12 +55,15 @@ typedef struct _rrMonitor {
ScreenPtr pScreen; ScreenPtr pScreen;
RRModePtr pModes; RRModePtr pModes;
void *identifier; /* made unique by DDX */ void *identifier; /* made unique by DDX */
int id; /* index in list of monitors */
Bool referenced; Bool referenced;
Bool oldReferenced;
Rotation rotations;
/* /*
* Current state * Current state
*/ */
int mode; RRModePtr pMode;
int x, y; int x, y;
Rotation rotation; Rotation rotation;
} RRMonitor, *RRMonitorPtr; } RRMonitor, *RRMonitorPtr;
@ -76,7 +87,18 @@ typedef Bool (*RRCloseScreenProcPtr) ( int i, ScreenPtr pscreen);
#ifdef RANDR_SCREEN_INTERFACE #ifdef RANDR_SCREEN_INTERFACE
typedef void *RRScreenSizePtr; typedef struct _rrRefresh {
CARD16 refresh;
RRModePtr pMode;
} RRRefreshRec, *RRRefreshPtr;
typedef struct _rrScreenSize {
int id;
short width, height;
short mmWidth, mmHeight;
int nrefresh;
RRRefreshPtr refresh;
} RRScreenSizeRec, *RRScreenSizePtr;
typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen, typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
Rotation rotation, Rotation rotation,
@ -87,12 +109,23 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr pScreen,
typedef struct _rrScrPriv { typedef struct _rrScrPriv {
RRSetModeProcPtr rrSetMode; /*
* 'public' part of the structure; DDXen fill this in
* as they initialize
*/
#ifdef RANDR_SCREEN_INTERFACE
RRSetConfigProcPtr rrSetConfig;
#endif
RRGetInfoProcPtr rrGetInfo; RRGetInfoProcPtr rrGetInfo;
RRCloseScreenProcPtr CloseScreen; RRSetScreenSizeProcPtr rrSetScreenSize;
RRSetModeProcPtr rrSetMode;
/*
* Private part of the structure; not considered part of the ABI
*/
TimeStamp lastSetTime; /* last changed by client */ TimeStamp lastSetTime; /* last changed by client */
TimeStamp lastConfigTime; /* possible configs changed */ TimeStamp lastConfigTime; /* possible configs changed */
RRCloseScreenProcPtr CloseScreen;
/* /*
* monitor data * monitor data
@ -105,7 +138,6 @@ typedef struct _rrScrPriv {
*/ */
Rotation rotations; Rotation rotations;
RRSetConfigProcPtr rrSetConfig;
Rotation rotation; Rotation rotation;
#endif #endif
@ -137,8 +169,7 @@ RRRegisterMonitor (ScreenPtr pScreen,
RRModePtr RRModePtr
RRRegisterMode (RRMonitorPtr pMonitor, RRRegisterMode (RRMonitorPtr pMonitor,
xRRMonitorMode *pMode, xRRMonitorMode *pMode,
char *name, char *name);
int nameLength);
/* /*
* Finally, set the current configuration of each monitor * Finally, set the current configuration of each monitor
@ -147,6 +178,8 @@ RRRegisterMode (RRMonitorPtr pMonitor,
void void
RRSetCurrentMode (RRMonitorPtr pMonitor, RRSetCurrentMode (RRMonitorPtr pMonitor,
RRModePtr pMode, RRModePtr pMode,
int x,
int y,
Rotation rotation); Rotation rotation);
Bool RRScreenInit(ScreenPtr pScreen); Bool RRScreenInit(ScreenPtr pScreen);
@ -167,6 +200,8 @@ Bool
miRRSetMode (ScreenPtr pScreen, miRRSetMode (ScreenPtr pScreen,
int monitor, int monitor,
RRModePtr pMode, RRModePtr pMode,
int x,
int y,
Rotation rotation); Rotation rotation);
#ifdef RANDR_SCREEN_INTERFACE #ifdef RANDR_SCREEN_INTERFACE