Allow RandR objects to be created before the associated ScreenRec.

xf86 drivers need to create RandR object in the PreInit stage,
before the ScreenRec is allocated. Changing the RandR DIX code
to permit this required the addition of functions that later associate the
objects with the related screen.

An additional change is that modes are now global, and no longer associated
with a specific screen. This change actually makes mode management cleaner
as there is no more per-screen list of modes to deal with.

This changes the RandR 1.2 ABI/API for drivers.
This commit is contained in:
Keith Packard 2006-11-08 21:36:35 -08:00
parent 20e9144c07
commit ec77a95a02
9 changed files with 255 additions and 170 deletions

View File

@ -51,7 +51,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h xf86Opt.h \
xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86Resources.h \ xf86PciInfo.h xf86Priv.h xf86Privstr.h xf86Resources.h \
xf86cmap.h xf86fbman.h xf86str.h $(XISDKINCS) \ xf86cmap.h xf86fbman.h xf86str.h $(XISDKINCS) \
$(XVSDKINCS) atKeynames.h xf86Version.h xorgVersion.h \ $(XVSDKINCS) atKeynames.h xf86Version.h xorgVersion.h \
xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h xf86sbusBus.h xf86xv.h xf86xvmc.h xf86xvpriv.h xf86Keymap.h
DISTCLEANFILES = xf86Build.h DISTCLEANFILES = xf86Build.h
CLEANFILES = $(BUILT_SOURCES) CLEANFILES = $(BUILT_SOURCES)

View File

@ -113,17 +113,24 @@ miRandRInit (ScreenPtr pScreen)
modeInfo.height = pScreen->height; modeInfo.height = pScreen->height;
modeInfo.nameLength = strlen (name); modeInfo.nameLength = strlen (name);
mode = RRModeGet (pScreen, &modeInfo, name); mode = RRModeGet (&modeInfo, name);
if (!mode) if (!mode)
return FALSE; return FALSE;
crtc = RRCrtcCreate (pScreen, NULL); crtc = RRCrtcCreate (NULL);
if (!crtc) if (!crtc)
return FALSE; return FALSE;
if (!RRCrtcAttachScreen (crtc, pScreen))
{
RRCrtcDestroy (crtc);
return FALSE;
}
output = RROutputCreate (pScreen, "screen", 6, NULL); output = RROutputCreate ("screen", 6, NULL);
if (!output) if (!output)
return FALSE; return FALSE;
if (!RROutputAttachScreen (output, pScreen))
return FALSE;
if (!RROutputSetClones (output, NULL, 0)) if (!RROutputSetClones (output, NULL, 0))
return FALSE; return FALSE;
if (!RROutputSetModes (output, &mode, 1, 0)) if (!RROutputSetModes (output, &mode, 1, 0))

View File

@ -103,8 +103,6 @@ RRCloseScreen (int i, ScreenPtr pScreen)
RRCrtcDestroy (pScrPriv->crtcs[j]); RRCrtcDestroy (pScrPriv->crtcs[j]);
for (j = pScrPriv->numOutputs - 1; j >= 0; j--) for (j = pScrPriv->numOutputs - 1; j >= 0; j--)
RROutputDestroy (pScrPriv->outputs[j]); RROutputDestroy (pScrPriv->outputs[j]);
for (j = pScrPriv->numModes - 1; j >= 0; j--)
RRModeDestroy (pScrPriv->modes[j]);
xfree (pScrPriv); xfree (pScrPriv);
RRNScreens -= 1; /* ok, one fewer screen with RandR running */ RRNScreens -= 1; /* ok, one fewer screen with RandR running */
@ -257,8 +255,6 @@ Bool RRScreenInit(ScreenPtr pScreen)
wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen); wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
pScrPriv->numModes = 0;
pScrPriv->modes = NULL;
pScrPriv->numOutputs = 0; pScrPriv->numOutputs = 0;
pScrPriv->outputs = NULL; pScrPriv->outputs = NULL;
pScrPriv->numCrtcs = 0; pScrPriv->numCrtcs = 0;

View File

@ -79,7 +79,6 @@ struct _rrMode {
xRRModeInfo mode; xRRModeInfo mode;
char *name; char *name;
void *devPrivate; void *devPrivate;
ScreenPtr screen;
Bool userDefined; Bool userDefined;
}; };
@ -210,10 +209,6 @@ typedef struct _rrScrPriv {
CARD16 width, height; /* last known screen size */ CARD16 width, height; /* last known screen size */
Bool layoutChanged; /* screen layout changed */ Bool layoutChanged; /* screen layout changed */
/* modes, outputs and crtcs */
int numModes;
RRModePtr *modes;
int numOutputs; int numOutputs;
RROutputPtr *outputs; RROutputPtr *outputs;
@ -457,9 +452,16 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
* Create a CRTC * Create a CRTC
*/ */
RRCrtcPtr RRCrtcPtr
RRCrtcCreate (ScreenPtr pScreen, RRCrtcCreate (void *devPrivate);
void *devPrivate);
/*
* Attach a CRTC to a screen. Once done, this cannot be
* undone without destroying the CRTC; it is separate from Create
* only to allow an xf86-based driver to create objects in preinit
*/
Bool
RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen);
/* /*
* Notify the extension that the Crtc has been reconfigured, * Notify the extension that the Crtc has been reconfigured,
* the driver calls this whenever it has updated the mode * the driver calls this whenever it has updated the mode
@ -556,8 +558,7 @@ RRClientKnowsRates (ClientPtr pClient);
*/ */
RRModePtr RRModePtr
RRModeGet (ScreenPtr pScreen, RRModeGet (xRRModeInfo *modeInfo,
xRRModeInfo *modeInfo,
const char *name); const char *name);
void void
@ -570,6 +571,12 @@ RRModePruneUnused (ScreenPtr pScreen);
void void
RRModeDestroy (RRModePtr mode); RRModeDestroy (RRModePtr mode);
/*
* Return a list of modes that are valid for some output in pScreen
*/
RRModePtr *
RRModesForScreen (ScreenPtr pScreen, int *num_ret);
/* /*
* Initialize mode type * Initialize mode type
*/ */
@ -601,11 +608,18 @@ RROutputChanged (RROutputPtr output);
*/ */
RROutputPtr RROutputPtr
RROutputCreate (ScreenPtr pScreen, RROutputCreate (const char *name,
const char *name,
int nameLength, int nameLength,
void *devPrivate); void *devPrivate);
/*
* Attach an output to a screen, again split from creation so
* xf86 DDXen can create randr resources before the ScreenRec
* exists
*/
Bool
RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen);
/* /*
* Notify extension that output parameters have been changed * Notify extension that output parameters have been changed
*/ */

View File

@ -32,43 +32,34 @@ void
RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged) RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
{ {
ScreenPtr pScreen = crtc->pScreen; ScreenPtr pScreen = crtc->pScreen;
rrScrPriv(pScreen);
crtc->changed = TRUE; crtc->changed = TRUE;
pScrPriv->changed = TRUE; if (pScreen)
/* {
* Send ConfigureNotify on any layout change rrScrPriv(pScreen);
*/
if (layoutChanged) pScrPriv->changed = TRUE;
pScrPriv->layoutChanged = TRUE; /*
* Send ConfigureNotify on any layout change
*/
if (layoutChanged)
pScrPriv->layoutChanged = TRUE;
}
} }
/* /*
* Create a CRTC * Create a CRTC
*/ */
RRCrtcPtr RRCrtcPtr
RRCrtcCreate (ScreenPtr pScreen, RRCrtcCreate (void *devPrivate)
void *devPrivate)
{ {
rrScrPriv (pScreen);
RRCrtcPtr crtc; RRCrtcPtr crtc;
RRCrtcPtr *crtcs;
crtc = xalloc (sizeof (RRCrtcRec)); crtc = xalloc (sizeof (RRCrtcRec));
if (!crtc) if (!crtc)
return NULL; 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->id = FakeClientID (0);
crtc->pScreen = pScreen; crtc->pScreen = NULL;
crtc->mode = NULL; crtc->mode = NULL;
crtc->x = 0; crtc->x = 0;
crtc->y = 0; crtc->y = 0;
@ -84,11 +75,37 @@ RRCrtcCreate (ScreenPtr pScreen,
if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc)) if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
return NULL; return NULL;
return crtc;
}
/*
* Attach a Crtc to a screen. This is done as a separate step
* so that an xf86-based driver can create CRTCs in PreInit
* before the Screen has been created
*/
Bool
RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen)
{
rrScrPriv (pScreen);
RRCrtcPtr *crtcs;
/* make space for the crtc pointer */
if (pScrPriv->numCrtcs)
crtcs = xrealloc (pScrPriv->crtcs,
(pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
else
crtcs = xalloc (sizeof (RRCrtcPtr));
if (!crtcs)
return FALSE;
/* attach the screen and crtc together */
crtc->pScreen = pScreen;
pScrPriv->crtcs = crtcs; pScrPriv->crtcs = crtcs;
pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc; pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
RRCrtcChanged (crtc, TRUE); RRCrtcChanged (crtc, TRUE);
return crtc; return TRUE;
} }
/* /*
@ -243,7 +260,6 @@ RRCrtcSet (RRCrtcPtr crtc,
RROutputConfigPtr outputs) RROutputConfigPtr outputs)
{ {
ScreenPtr pScreen = crtc->pScreen; ScreenPtr pScreen = crtc->pScreen;
rrScrPriv(pScreen);
/* See if nothing changed */ /* See if nothing changed */
if (crtc->mode == mode && if (crtc->mode == mode &&
@ -255,45 +271,49 @@ RRCrtcSet (RRCrtcPtr crtc,
{ {
return TRUE; return TRUE;
} }
#if RANDR_12_INTERFACE if (pScreen)
if (pScrPriv->rrCrtcSet)
{ {
return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, #if RANDR_12_INTERFACE
rotation, numOutputs, outputs); rrScrPriv(pScreen);
} if (pScrPriv->rrCrtcSet)
{
return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
rotation, numOutputs, outputs);
}
#endif #endif
#if RANDR_10_INTERFACE #if RANDR_10_INTERFACE
if (pScrPriv->rrSetConfig) if (pScrPriv->rrSetConfig)
{ {
RRScreenSize size; RRScreenSize size;
RRScreenRate rate; RRScreenRate rate;
Bool ret; Bool ret;
size.width = mode->mode.width; size.width = mode->mode.width;
size.height = mode->mode.height; size.height = mode->mode.height;
if (outputs[0].output->mmWidth && outputs[0].output->mmHeight) if (outputs[0].output->mmWidth && outputs[0].output->mmHeight)
{ {
size.mmWidth = outputs[0].output->mmWidth; size.mmWidth = outputs[0].output->mmWidth;
size.mmHeight = outputs[0].output->mmHeight; size.mmHeight = outputs[0].output->mmHeight;
}
else
{
size.mmWidth = pScreen->mmWidth;
size.mmHeight = pScreen->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)
RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
return ret;
} }
else
{
size.mmWidth = pScreen->mmWidth;
size.mmHeight = pScreen->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)
RRCrtcNotify (crtc, mode, x, y, rotation, 1, &outputs[0].output);
return ret;
}
#endif #endif
RRTellChanged (pScreen); RRTellChanged (pScreen);
}
return FALSE; return FALSE;
} }
@ -311,22 +331,26 @@ RRCrtcDestroyResource (pointer value, XID pid)
{ {
RRCrtcPtr crtc = (RRCrtcPtr) value; RRCrtcPtr crtc = (RRCrtcPtr) value;
ScreenPtr pScreen = crtc->pScreen; ScreenPtr pScreen = crtc->pScreen;
rrScrPriv(pScreen);
int i;
for (i = 0; i < pScrPriv->numCrtcs; i++) if (pScreen)
{ {
if (pScrPriv->crtcs[i] == crtc) rrScrPriv(pScreen);
int i;
for (i = 0; i < pScrPriv->numCrtcs; i++)
{ {
memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1, if (pScrPriv->crtcs[i] == crtc)
(pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr)); {
--pScrPriv->numCrtcs; memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
break; (pScrPriv->numCrtcs - (i - 1)) * sizeof (RRCrtcPtr));
--pScrPriv->numCrtcs;
break;
}
} }
} }
if (crtc->gammaRed) if (crtc->gammaRed)
xfree (crtc->gammaRed); xfree (crtc->gammaRed);
xfree (value); xfree (crtc);
return 1; return 1;
} }
@ -343,15 +367,18 @@ RRCrtcGammaSet (RRCrtcPtr crtc,
Bool ret = TRUE; Bool ret = TRUE;
#if RANDR_12_INTERFACE #if RANDR_12_INTERFACE
ScreenPtr pScreen = crtc->pScreen; ScreenPtr pScreen = crtc->pScreen;
rrScrPriv(pScreen);
#endif #endif
memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16)); memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16)); memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16)); memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
#if RANDR_12_INTERFACE #if RANDR_12_INTERFACE
if (pScrPriv->rrCrtcSetGamma) if (pScreen)
ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc); {
rrScrPriv(pScreen);
if (pScrPriv->rrCrtcSetGamma)
ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
}
#endif #endif
return ret; return ret;
} }
@ -433,6 +460,9 @@ ProcRRGetCrtcInfo (ClientPtr client)
if (!crtc) if (!crtc)
return RRErrorBase + BadRRCrtc; return RRErrorBase + BadRRCrtc;
/* All crtcs must be associated with screens before client
* requests are processed
*/
pScreen = crtc->pScreen; pScreen = crtc->pScreen;
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
@ -589,7 +619,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
for (j = 0; j < outputs[i].output->numCrtcs; j++) for (j = 0; j < outputs[i].output->numCrtcs; j++)
if (outputs[i].output->crtcs[j] == crtc) if (outputs[i].output->crtcs[j] == crtc)
break; break;
if (j == outputs[j].output->numCrtcs) if (j == outputs[i].output->numCrtcs)
{ {
if (outputs) if (outputs)
xfree (outputs); xfree (outputs);

View File

@ -44,7 +44,7 @@ RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height * modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
(CARD32) refresh); (CARD32) refresh);
modeInfo.nameLength = strlen (name); modeInfo.nameLength = strlen (name);
mode = RRModeGet (pScreen, &modeInfo, name); mode = RRModeGet (&modeInfo, name);
if (!mode) if (!mode)
return NULL; return NULL;
for (i = 0; i < output->numModes; i++) for (i = 0; i < output->numModes; i++)
@ -90,12 +90,19 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
if (pScrPriv->numOutputs == 0 && if (pScrPriv->numOutputs == 0 &&
pScrPriv->numCrtcs == 0) pScrPriv->numCrtcs == 0)
{ {
crtc = RRCrtcCreate (pScreen, NULL); crtc = RRCrtcCreate (NULL);
if (!crtc) if (!crtc)
return; return;
output = RROutputCreate (pScreen, "default", 7, NULL); if (!RRCrtcAttachScreen (crtc, pScreen))
{
RRCrtcDestroy (crtc);
return;
}
output = RROutputCreate ("default", 7, NULL);
if (!output) if (!output)
return; return;
if (!RROutputAttachScreen (output, pScreen))
return;
RROutputSetCrtcs (output, &crtc, 1); RROutputSetCrtcs (output, &crtc, 1);
RROutputSetCrtc (output, crtc); RROutputSetCrtc (output, crtc);
RROutputSetConnection (output, RR_Connected); RROutputSetConnection (output, RR_Connected);
@ -206,7 +213,6 @@ RRGetInfo (ScreenPtr pScreen)
if (pScrPriv->nSizes) if (pScrPriv->nSizes)
RRScanOldConfig (pScreen, rotations); RRScanOldConfig (pScreen, rotations);
#endif #endif
RRModePruneUnused (pScreen);
RRTellChanged (pScreen); RRTellChanged (pScreen);
return TRUE; return TRUE;
} }

View File

@ -42,19 +42,23 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo *b)
return TRUE; return TRUE;
} }
/*
* Keep a list so it's easy to find modes in the resource database.
*/
static int num_modes;
static RRModePtr *modes;
RRModePtr RRModePtr
RRModeGet (ScreenPtr pScreen, RRModeGet (xRRModeInfo *modeInfo,
xRRModeInfo *modeInfo,
const char *name) const char *name)
{ {
rrScrPriv (pScreen);
int i; int i;
RRModePtr mode; RRModePtr mode;
RRModePtr *modes; RRModePtr *newModes;
for (i = 0; i < pScrPriv->numModes; i++) for (i = 0; i < num_modes; i++)
{ {
mode = pScrPriv->modes[i]; mode = modes[i];
if (RRModeEqual (&mode->mode, modeInfo) && if (RRModeEqual (&mode->mode, modeInfo) &&
!memcmp (name, mode->name, modeInfo->nameLength)) !memcmp (name, mode->name, modeInfo->nameLength))
{ {
@ -71,16 +75,14 @@ RRModeGet (ScreenPtr pScreen,
mode->name = (char *) (mode + 1); mode->name = (char *) (mode + 1);
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->userDefined = FALSE; mode->userDefined = FALSE;
if (pScrPriv->numModes) if (num_modes)
modes = xrealloc (pScrPriv->modes, newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
(pScrPriv->numModes + 1) * sizeof (RRModePtr));
else else
modes = xalloc (sizeof (RRModePtr)); newModes = xalloc (sizeof (RRModePtr));
if (!modes) if (!newModes)
{ {
xfree (mode); xfree (mode);
return NULL; return NULL;
@ -89,37 +91,64 @@ RRModeGet (ScreenPtr pScreen,
mode->mode.id = FakeClientID(0); mode->mode.id = FakeClientID(0);
if (!AddResource (mode->mode.id, RRModeType, (pointer) mode)) if (!AddResource (mode->mode.id, RRModeType, (pointer) mode))
return NULL; return NULL;
modes = newModes;
modes[num_modes++] = mode;
/*
* give the caller a reference to this mode
*/
++mode->refcnt; ++mode->refcnt;
pScrPriv->modes = modes;
pScrPriv->modes[pScrPriv->numModes++] = mode;
pScrPriv->changed = TRUE;
return mode; return mode;
} }
RRModePtr *
RRModesForScreen (ScreenPtr pScreen, int *num_ret)
{
rrScrPriv(pScreen);
int o;
RRModePtr *screen_modes;
int num_screen_modes = 0;
screen_modes = xalloc ((num_modes ? num_modes : 1) * sizeof (RRModePtr));
for (o = 0; o < pScrPriv->numOutputs; o++)
{
RROutputPtr output = pScrPriv->outputs[o];
int m, n;
for (m = 0; m < output->numModes; m++)
{
RRModePtr mode = output->modes[m];
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
}
*num_ret = num_screen_modes;
return screen_modes;
}
void void
RRModeDestroy (RRModePtr mode) RRModeDestroy (RRModePtr mode)
{ {
ScreenPtr pScreen;
rrScrPrivPtr pScrPriv;
int m; int m;
if (--mode->refcnt > 0) if (--mode->refcnt > 0)
return; return;
pScreen = mode->screen; for (m = 0; m < num_modes; m++)
pScrPriv = rrGetScrPriv (pScreen);
for (m = 0; m < pScrPriv->numModes; m++)
{ {
if (pScrPriv->modes[m] == mode) if (modes[m] == mode)
{ {
memmove (pScrPriv->modes + m, pScrPriv->modes + m + 1, memmove (modes + m, modes + m + 1,
(pScrPriv->numModes - m - 1) * sizeof (RRModePtr)); (num_modes - m - 1) * sizeof (RRModePtr));
pScrPriv->numModes--; num_modes--;
if (!pScrPriv->numModes) if (!num_modes)
{ {
xfree (pScrPriv->modes); xfree (modes);
pScrPriv->modes = NULL; modes = NULL;
} }
pScrPriv->changed = TRUE;
break; break;
} }
} }
@ -137,6 +166,8 @@ RRModeDestroyResource (pointer value, XID pid)
Bool Bool
RRModeInit (void) RRModeInit (void)
{ {
assert (num_modes == 0);
assert (modes == NULL);
RRModeType = CreateNewResourceType (RRModeDestroyResource); RRModeType = CreateNewResourceType (RRModeDestroyResource);
if (!RRModeType) if (!RRModeType)
return FALSE; return FALSE;
@ -146,26 +177,6 @@ RRModeInit (void)
return TRUE; return TRUE;
} }
void
RRModePruneUnused (ScreenPtr pScreen)
{
rrScrPriv (pScreen);
RRModePtr *unused, mode;
int m;
int num = pScrPriv->numModes;
unused = xalloc (num * sizeof (RRModePtr));
if (!unused)
return;
memcpy (unused, pScrPriv->modes, num * sizeof (RRModePtr));
for (m = 0; m < num; m++) {
mode = unused[m];
if (mode->refcnt == 1 && !mode->userDefined)
FreeResource (mode->mode.id, 0);
}
xfree (unused);
}
int int
ProcRRCreateMode (ClientPtr client) ProcRRCreateMode (ClientPtr client)
{ {
@ -205,4 +216,3 @@ ProcRRDeleteOutputMode (ClientPtr client)
(void) stuff; (void) stuff;
return BadImplementation; return BadImplementation;
} }

View File

@ -42,30 +42,17 @@ RROutputChanged (RROutputPtr output)
*/ */
RROutputPtr RROutputPtr
RROutputCreate (ScreenPtr pScreen, RROutputCreate (const char *name,
const char *name,
int nameLength, int nameLength,
void *devPrivate) void *devPrivate)
{ {
rrScrPriv (pScreen);
RROutputPtr output; RROutputPtr output;
RROutputPtr *outputs;
output = xalloc (sizeof (RROutputRec) + nameLength + 1); output = xalloc (sizeof (RROutputRec) + nameLength + 1);
if (!output) if (!output)
return NULL; return NULL;
if (pScrPriv->numOutputs)
outputs = xrealloc (pScrPriv->outputs,
(pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
else
outputs = xalloc (sizeof (RROutputPtr));
if (!outputs)
{
xfree (output);
return NULL;
}
output->id = FakeClientID (0); output->id = FakeClientID (0);
output->pScreen = pScreen; output->pScreen = NULL;
output->name = (char *) (output + 1); output->name = (char *) (output + 1);
output->nameLength = nameLength; output->nameLength = nameLength;
memcpy (output->name, name, nameLength); memcpy (output->name, name, nameLength);
@ -91,12 +78,35 @@ RROutputCreate (ScreenPtr pScreen,
if (!AddResource (output->id, RROutputType, (pointer) output)) if (!AddResource (output->id, RROutputType, (pointer) output))
return NULL; return NULL;
pScrPriv->outputs = outputs;
pScrPriv->outputs[pScrPriv->numOutputs++] = output;
RROutputChanged (output);
return output; 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 = xrealloc (pScrPriv->outputs,
(pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
else
outputs = xalloc (sizeof (RROutputPtr));
if (!outputs)
return FALSE;
output->pScreen = pScreen;
pScrPriv->outputs = outputs;
pScrPriv->outputs[pScrPriv->numOutputs++] = output;
RROutputChanged (output);
return TRUE;
}
/* /*
* Notify extension that output parameters have been changed * Notify extension that output parameters have been changed
*/ */

View File

@ -360,6 +360,13 @@ ProcRRGetScreenResources (ClientPtr client)
} }
else else
{ {
RRModePtr *modes;
int num_modes;
modes = RRModesForScreen (pScreen, &num_modes);
if (!modes)
return BadAlloc;
rep.type = X_Reply; rep.type = X_Reply;
rep.sequenceNumber = client->sequence; rep.sequenceNumber = client->sequence;
rep.length = 0; rep.length = 0;
@ -367,15 +374,15 @@ ProcRRGetScreenResources (ClientPtr client)
rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds; rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
rep.nCrtcs = pScrPriv->numCrtcs; rep.nCrtcs = pScrPriv->numCrtcs;
rep.nOutputs = pScrPriv->numOutputs; rep.nOutputs = pScrPriv->numOutputs;
rep.nModes = pScrPriv->numModes;; rep.nModes = num_modes;
rep.nbytesNames = 0; rep.nbytesNames = 0;
for (i = 0; i < pScrPriv->numModes; i++) for (i = 0; i < num_modes; i++)
rep.nbytesNames += pScrPriv->modes[i]->mode.nameLength; rep.nbytesNames += modes[i]->mode.nameLength;
rep.length = (pScrPriv->numCrtcs + rep.length = (pScrPriv->numCrtcs +
pScrPriv->numOutputs + pScrPriv->numOutputs +
pScrPriv->numModes * (SIZEOF(xRRModeInfo) >> 2) + num_modes * (SIZEOF(xRRModeInfo) >> 2) +
((rep.nbytesNames + 3) >> 2)); ((rep.nbytesNames + 3) >> 2));
extraLen = rep.length << 2; extraLen = rep.length << 2;
@ -383,7 +390,10 @@ ProcRRGetScreenResources (ClientPtr client)
{ {
extra = xalloc (extraLen); extra = xalloc (extraLen);
if (!extra) if (!extra)
{
xfree (modes);
return BadAlloc; return BadAlloc;
}
} }
else else
extra = NULL; extra = NULL;
@ -391,7 +401,7 @@ ProcRRGetScreenResources (ClientPtr client)
crtcs = (RRCrtc *) extra; crtcs = (RRCrtc *) extra;
outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
names = (CARD8 *) (modeinfos + pScrPriv->numModes); names = (CARD8 *) (modeinfos + num_modes);
for (i = 0; i < pScrPriv->numCrtcs; i++) for (i = 0; i < pScrPriv->numCrtcs; i++)
{ {
@ -407,9 +417,10 @@ ProcRRGetScreenResources (ClientPtr client)
swapl (&outputs[i], n); swapl (&outputs[i], n);
} }
for (i = 0; i < pScrPriv->numModes; i++) for (i = 0; i < num_modes; i++)
{ {
modeinfos[i] = pScrPriv->modes[i]->mode; RRModePtr mode = modes[i];
modeinfos[i] = mode->mode;
if (client->swapped) if (client->swapped)
{ {
swapl (&modeinfos[i].id, n); swapl (&modeinfos[i].id, n);
@ -426,10 +437,11 @@ ProcRRGetScreenResources (ClientPtr client)
swaps (&modeinfos[i].nameLength, n); swaps (&modeinfos[i].nameLength, n);
swapl (&modeinfos[i].modeFlags, n); swapl (&modeinfos[i].modeFlags, n);
} }
memcpy (names, pScrPriv->modes[i]->name, memcpy (names, mode->name,
pScrPriv->modes[i]->mode.nameLength); mode->mode.nameLength);
names += pScrPriv->modes[i]->mode.nameLength; names += mode->mode.nameLength;
} }
xfree (modes);
assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length); assert (((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
} }