Steal Xinerama code from SiS driver. Add missing files.
Provide a Xinerama implementation when DIX version isn't enabled. This version exposes each crtc as a separate 'screen' and reports the size of that patch. The extension also sends ConfigureNotify events to the root window whenever crtcs change so that applications will re-fetch xinerama information. This actually works for metacity.
This commit is contained in:
337
randr/rrinfo.c
Normal file
337
randr/rrinfo.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright © 2006 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "randrstr.h"
|
||||
|
||||
#ifdef RANDR_10_INTERFACE
|
||||
static RRModePtr
|
||||
RROldModeAdd (RROutputPtr output, RRScreenSizePtr size, int refresh)
|
||||
{
|
||||
ScreenPtr pScreen = output->pScreen;
|
||||
rrScrPriv(pScreen);
|
||||
xRRModeInfo modeInfo;
|
||||
char name[100];
|
||||
RRModePtr mode;
|
||||
int i;
|
||||
RRModePtr *modes;
|
||||
|
||||
memset (&modeInfo, '\0', sizeof (modeInfo));
|
||||
sprintf (name, "%dx%d", size->width, size->height);
|
||||
|
||||
modeInfo.width = size->width;
|
||||
modeInfo.height = size->height;
|
||||
modeInfo.mmWidth = size->mmWidth;
|
||||
modeInfo.mmHeight = size->mmHeight;
|
||||
modeInfo.hTotal = size->width;
|
||||
modeInfo.vTotal = size->height;
|
||||
modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height *
|
||||
(CARD32) refresh);
|
||||
modeInfo.nameLength = strlen (name);
|
||||
mode = RRModeGet (pScreen, &modeInfo, name);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
for (i = 0; i < output->numModes; i++)
|
||||
if (output->modes[i] == mode)
|
||||
{
|
||||
RRModeDestroy (mode);
|
||||
return mode;
|
||||
}
|
||||
|
||||
if (output->numModes)
|
||||
modes = xrealloc (output->modes,
|
||||
(output->numModes + 1) * sizeof (RRModePtr));
|
||||
else
|
||||
modes = xalloc (sizeof (RRModePtr));
|
||||
if (!modes)
|
||||
{
|
||||
RRModeDestroy (mode);
|
||||
FreeResource (mode->mode.id, 0);
|
||||
return NULL;
|
||||
}
|
||||
modes[output->numModes++] = mode;
|
||||
output->modes = modes;
|
||||
output->changed = TRUE;
|
||||
pScrPriv->changed = TRUE;
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void
|
||||
RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
|
||||
{
|
||||
rrScrPriv(pScreen);
|
||||
RROutputPtr output;
|
||||
RRCrtcPtr crtc;
|
||||
RRModePtr mode, newMode = NULL;
|
||||
int i;
|
||||
CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT;
|
||||
CARD16 maxWidth = 0, maxHeight = 0;
|
||||
|
||||
/*
|
||||
* First time through, create a crtc and output and hook
|
||||
* them together
|
||||
*/
|
||||
if (pScrPriv->numOutputs == 0 &&
|
||||
pScrPriv->numCrtcs == 0)
|
||||
{
|
||||
crtc = RRCrtcCreate (pScreen, NULL);
|
||||
if (!crtc)
|
||||
return;
|
||||
output = RROutputCreate (pScreen, "default", 7, NULL);
|
||||
if (!output)
|
||||
return;
|
||||
RROutputSetCrtcs (output, &crtc, 1);
|
||||
RROutputSetCrtc (output, crtc);
|
||||
RROutputSetConnection (output, RR_Connected);
|
||||
#ifdef RENDER
|
||||
RROutputSetSubpixelOrder (output, PictureGetSubpixelOrder (pScreen));
|
||||
#endif
|
||||
}
|
||||
|
||||
output = RRFirstOutput (pScreen);
|
||||
if (!output)
|
||||
return;
|
||||
crtc = output->crtc;
|
||||
|
||||
/* check rotations */
|
||||
if (rotations != crtc->rotations)
|
||||
{
|
||||
crtc->rotations = rotations;
|
||||
crtc->changed = TRUE;
|
||||
pScrPriv->changed = TRUE;
|
||||
}
|
||||
|
||||
/* regenerate mode list */
|
||||
for (i = 0; i < pScrPriv->nSizes; i++)
|
||||
{
|
||||
RRScreenSizePtr size = &pScrPriv->pSizes[i];
|
||||
int r;
|
||||
|
||||
if (size->nRates)
|
||||
{
|
||||
for (r = 0; r < size->nRates; r++)
|
||||
{
|
||||
mode = RROldModeAdd (output, size, size->pRates[r].rate);
|
||||
if (i == pScrPriv->size &&
|
||||
size->pRates[r].rate == pScrPriv->rate)
|
||||
{
|
||||
newMode = mode;
|
||||
}
|
||||
}
|
||||
xfree (size->pRates);
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = RROldModeAdd (output, size, 0);
|
||||
if (i == pScrPriv->size)
|
||||
newMode = mode;
|
||||
}
|
||||
}
|
||||
if (pScrPriv->nSizes)
|
||||
xfree (pScrPriv->pSizes);
|
||||
pScrPriv->pSizes = NULL;
|
||||
pScrPriv->nSizes = 0;
|
||||
|
||||
/* find size bounds */
|
||||
for (i = 0; i < output->numModes; i++)
|
||||
{
|
||||
RRModePtr mode = output->modes[i];
|
||||
CARD16 width = mode->mode.width;
|
||||
CARD16 height = mode->mode.height;
|
||||
|
||||
if (width < minWidth) minWidth = width;
|
||||
if (width > maxWidth) maxWidth = width;
|
||||
if (height < minHeight) minHeight = height;
|
||||
if (height > maxHeight) maxHeight = height;
|
||||
}
|
||||
|
||||
if (minWidth != pScrPriv->minWidth) {
|
||||
pScrPriv->minWidth = minWidth; pScrPriv->changed = TRUE;
|
||||
}
|
||||
if (maxWidth != pScrPriv->maxWidth) {
|
||||
pScrPriv->maxWidth = maxWidth; pScrPriv->changed = TRUE;
|
||||
}
|
||||
if (minHeight != pScrPriv->minHeight) {
|
||||
pScrPriv->minHeight = minHeight; pScrPriv->changed = TRUE;
|
||||
}
|
||||
if (maxHeight != pScrPriv->maxHeight) {
|
||||
pScrPriv->maxHeight = maxHeight; pScrPriv->changed = TRUE;
|
||||
}
|
||||
|
||||
/* notice current mode */
|
||||
if (newMode)
|
||||
RRCrtcNotify (output->crtc, newMode, 0, 0, pScrPriv->rotation,
|
||||
1, &output);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Poll the driver for changed information
|
||||
*/
|
||||
Bool
|
||||
RRGetInfo (ScreenPtr pScreen)
|
||||
{
|
||||
rrScrPriv (pScreen);
|
||||
Rotation rotations;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pScrPriv->numOutputs; i++)
|
||||
pScrPriv->outputs[i]->changed = FALSE;
|
||||
for (i = 0; i < pScrPriv->numCrtcs; i++)
|
||||
pScrPriv->crtcs[i]->changed = FALSE;
|
||||
|
||||
rotations = 0;
|
||||
pScrPriv->changed = FALSE;
|
||||
|
||||
if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations))
|
||||
return FALSE;
|
||||
|
||||
#if RANDR_10_INTERFACE
|
||||
if (pScrPriv->nSizes)
|
||||
RRScanOldConfig (pScreen, rotations);
|
||||
#endif
|
||||
RRTellChanged (pScreen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if RANDR_12_INTERFACE
|
||||
/*
|
||||
* Register the range of sizes for the screen
|
||||
*/
|
||||
void
|
||||
RRScreenSetSizeRange (ScreenPtr pScreen,
|
||||
CARD16 minWidth,
|
||||
CARD16 minHeight,
|
||||
CARD16 maxWidth,
|
||||
CARD16 maxHeight)
|
||||
{
|
||||
rrScrPriv (pScreen);
|
||||
|
||||
if (!pScrPriv)
|
||||
return;
|
||||
pScrPriv->minWidth = minWidth;
|
||||
pScrPriv->minHeight = minHeight;
|
||||
pScrPriv->maxWidth = maxWidth;
|
||||
pScrPriv->maxHeight = maxHeight;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef RANDR_10_INTERFACE
|
||||
static Bool
|
||||
RRScreenSizeMatches (RRScreenSizePtr a,
|
||||
RRScreenSizePtr b)
|
||||
{
|
||||
if (a->width != b->width)
|
||||
return FALSE;
|
||||
if (a->height != b->height)
|
||||
return FALSE;
|
||||
if (a->mmWidth != b->mmWidth)
|
||||
return FALSE;
|
||||
if (a->mmHeight != b->mmHeight)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
RRScreenSizePtr
|
||||
RRRegisterSize (ScreenPtr pScreen,
|
||||
short width,
|
||||
short height,
|
||||
short mmWidth,
|
||||
short mmHeight)
|
||||
{
|
||||
rrScrPriv (pScreen);
|
||||
int i;
|
||||
RRScreenSize tmp;
|
||||
RRScreenSizePtr pNew;
|
||||
|
||||
if (!pScrPriv)
|
||||
return 0;
|
||||
|
||||
tmp.id = 0;
|
||||
tmp.width = width;
|
||||
tmp.height= height;
|
||||
tmp.mmWidth = mmWidth;
|
||||
tmp.mmHeight = mmHeight;
|
||||
tmp.pRates = 0;
|
||||
tmp.nRates = 0;
|
||||
for (i = 0; i < pScrPriv->nSizes; i++)
|
||||
if (RRScreenSizeMatches (&tmp, &pScrPriv->pSizes[i]))
|
||||
return &pScrPriv->pSizes[i];
|
||||
pNew = xrealloc (pScrPriv->pSizes,
|
||||
(pScrPriv->nSizes + 1) * sizeof (RRScreenSize));
|
||||
if (!pNew)
|
||||
return 0;
|
||||
pNew[pScrPriv->nSizes++] = tmp;
|
||||
pScrPriv->pSizes = pNew;
|
||||
return &pNew[pScrPriv->nSizes-1];
|
||||
}
|
||||
|
||||
Bool RRRegisterRate (ScreenPtr pScreen,
|
||||
RRScreenSizePtr pSize,
|
||||
int rate)
|
||||
{
|
||||
rrScrPriv(pScreen);
|
||||
int i;
|
||||
RRScreenRatePtr pNew, pRate;
|
||||
|
||||
if (!pScrPriv)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < pSize->nRates; i++)
|
||||
if (pSize->pRates[i].rate == rate)
|
||||
return TRUE;
|
||||
|
||||
pNew = xrealloc (pSize->pRates,
|
||||
(pSize->nRates + 1) * sizeof (RRScreenRate));
|
||||
if (!pNew)
|
||||
return FALSE;
|
||||
pRate = &pNew[pSize->nRates++];
|
||||
pRate->rate = rate;
|
||||
pSize->pRates = pNew;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Rotation
|
||||
RRGetRotation(ScreenPtr pScreen)
|
||||
{
|
||||
RROutputPtr output = RRFirstOutput (pScreen);
|
||||
|
||||
if (!output)
|
||||
return RR_Rotate_0;
|
||||
|
||||
return output->crtc->rotation;
|
||||
}
|
||||
|
||||
void
|
||||
RRSetCurrentConfig (ScreenPtr pScreen,
|
||||
Rotation rotation,
|
||||
int rate,
|
||||
RRScreenSizePtr pSize)
|
||||
{
|
||||
rrScrPriv (pScreen);
|
||||
|
||||
if (!pScrPriv)
|
||||
return;
|
||||
pScrPriv->size = pSize - pScrPriv->pSizes;
|
||||
pScrPriv->rotation = rotation;
|
||||
pScrPriv->rate = rate;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user