mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2025-12-21 00:30:04 +01:00
1358 lines
31 KiB
C
1358 lines
31 KiB
C
/*
|
|
* Copyright © 2008 Novell, 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
|
|
* Novell, Inc. not be used in advertising or publicity pertaining to
|
|
* distribution of the software without specific, written prior permission.
|
|
* Novell, Inc. makes no representations about the suitability of this
|
|
* software for any purpose. It is provided "as is" without express or
|
|
* implied warranty.
|
|
*
|
|
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
* NO EVENT SHALL NOVELL, INC. 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.
|
|
*
|
|
* Author: David Reveman <davidr@novell.com>
|
|
*/
|
|
|
|
#ifdef HAVE_DMX_CONFIG_H
|
|
#include <dmx-config.h>
|
|
#endif
|
|
|
|
#ifdef RANDR
|
|
#include "dmx.h"
|
|
#include "dmxlog.h"
|
|
#include "dmxextension.h"
|
|
#include "dmxcb.h"
|
|
#include "dmxrandr.h"
|
|
#include "dmxclient.h"
|
|
#include "dmxatom.h"
|
|
#include "dmxwindow.h"
|
|
|
|
#ifdef PANORAMIX
|
|
#include "panoramiX.h"
|
|
#include "panoramiXsrv.h"
|
|
#endif
|
|
|
|
#include <xcb/randr.h>
|
|
|
|
static int xRROutputsForFirstScreen = 1;
|
|
static int xRRCrtcsForFirstScreen = 1;
|
|
|
|
static DMXScreenInfo *
|
|
dmxRRGetScreenForCrtc (ScreenPtr pScreen,
|
|
RRCrtcPtr crtc)
|
|
{
|
|
int i;
|
|
|
|
rrScrPriv (pScreen);
|
|
|
|
for (i = 0; i < pScrPriv->numCrtcs; i++)
|
|
if (pScrPriv->crtcs[i] == crtc)
|
|
break;
|
|
|
|
if (i == pScrPriv->numCrtcs)
|
|
return NULL;
|
|
|
|
if (i < xRRCrtcsForFirstScreen)
|
|
return dmxScreens;
|
|
|
|
return &dmxScreens[((i - xRRCrtcsForFirstScreen) / xRRCrtcsPerScreen) + 1];
|
|
}
|
|
|
|
static DMXScreenInfo *
|
|
dmxRRGetScreenForOutput (ScreenPtr pScreen,
|
|
RROutputPtr output)
|
|
{
|
|
int i;
|
|
|
|
rrScrPriv (pScreen);
|
|
|
|
for (i = 0; i < pScrPriv->numOutputs; i++)
|
|
if (pScrPriv->outputs[i] == output)
|
|
break;
|
|
|
|
if (i == pScrPriv->numOutputs)
|
|
return NULL;
|
|
|
|
if (i < xRROutputsForFirstScreen)
|
|
return dmxScreens;
|
|
|
|
return &dmxScreens[((i - xRROutputsForFirstScreen) / xRROutputsPerScreen) +
|
|
1];
|
|
}
|
|
|
|
static RRModePtr
|
|
dmxRRGetMode (XRRScreenResources *r,
|
|
unsigned long mode)
|
|
{
|
|
xRRModeInfo modeInfo;
|
|
int i;
|
|
|
|
for (i = 0; i < r->nmode; i++)
|
|
{
|
|
if (r->modes[i].id == mode)
|
|
{
|
|
memset (&modeInfo, '\0', sizeof (modeInfo));
|
|
|
|
modeInfo.width = r->modes[i].width;
|
|
modeInfo.height = r->modes[i].height;
|
|
modeInfo.dotClock = r->modes[i].dotClock;
|
|
modeInfo.hSyncStart = r->modes[i].hSyncStart;
|
|
modeInfo.hSyncEnd = r->modes[i].hSyncEnd;
|
|
modeInfo.hTotal = r->modes[i].hTotal;
|
|
modeInfo.hSkew = r->modes[i].hSkew;
|
|
modeInfo.vSyncStart = r->modes[i].vSyncStart;
|
|
modeInfo.vSyncEnd = r->modes[i].vSyncEnd;
|
|
modeInfo.vTotal = r->modes[i].vTotal;
|
|
modeInfo.nameLength = strlen (r->modes[i].name);
|
|
modeInfo.modeFlags = r->modes[i].modeFlags;
|
|
|
|
return RRModeGet (&modeInfo, r->modes[i].name);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static RRCrtcPtr
|
|
dmxRRGetCrtc (ScreenPtr pScreen,
|
|
DMXScreenInfo *dmxScreen,
|
|
unsigned long crtc)
|
|
{
|
|
int baseCrtc = 0;
|
|
int numCrtc = xRRCrtcsForFirstScreen;
|
|
int i;
|
|
|
|
rrScrPriv (pScreen);
|
|
|
|
if (!crtc)
|
|
return NULL;
|
|
|
|
if (dmxScreen != dmxScreens)
|
|
{
|
|
baseCrtc = xRRCrtcsForFirstScreen +
|
|
((dmxScreen - dmxScreens) - 1) * xRRCrtcsPerScreen;
|
|
numCrtc = xRRCrtcsPerScreen;
|
|
}
|
|
|
|
for (i = 0; i < numCrtc; i++)
|
|
if (pScrPriv->crtcs[baseCrtc + i]->devPrivate == (void *) crtc)
|
|
return pScrPriv->crtcs[baseCrtc + i];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static RROutputPtr
|
|
dmxRRGetOutput (ScreenPtr pScreen,
|
|
DMXScreenInfo *dmxScreen,
|
|
unsigned long output)
|
|
{
|
|
int baseOutput = 0;
|
|
int numOutput = xRROutputsForFirstScreen;
|
|
int i;
|
|
|
|
rrScrPriv (pScreen);
|
|
|
|
if (!output)
|
|
return NULL;
|
|
|
|
if (dmxScreen != dmxScreens)
|
|
{
|
|
baseOutput = xRROutputsForFirstScreen +
|
|
((dmxScreen - dmxScreens) - 1) * xRROutputsPerScreen;
|
|
numOutput = xRROutputsPerScreen;
|
|
}
|
|
|
|
for (i = 0; i < numOutput; i++)
|
|
if (pScrPriv->outputs[baseOutput + i]->devPrivate == (void *) output)
|
|
return pScrPriv->outputs[baseOutput + i];
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRUpdateCrtc (ScreenPtr pScreen,
|
|
DMXScreenInfo *dmxScreen,
|
|
XRRScreenResources *r,
|
|
unsigned long xcrtc)
|
|
{
|
|
XRRCrtcInfo *c = NULL;
|
|
RRCrtcPtr crtc;
|
|
RRModePtr mode = NULL;
|
|
RROutputPtr *outputs = NULL;
|
|
XRRCrtcGamma *gamma = NULL;
|
|
int i, noutput = 0;
|
|
|
|
crtc = dmxRRGetCrtc (pScreen, dmxScreen, xcrtc);
|
|
if (!crtc)
|
|
return TRUE; /* do nothing if the crtc doesn't exist */
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
c = XRRGetCrtcInfo (dmxScreen->beDisplay, r, xcrtc);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!c)
|
|
return FALSE;
|
|
|
|
if (c->noutput)
|
|
{
|
|
outputs = xalloc (sizeof (RROutputPtr) * c->noutput);
|
|
if (!outputs)
|
|
return FALSE;
|
|
}
|
|
|
|
if (c->mode)
|
|
mode = dmxRRGetMode (r, c->mode);
|
|
|
|
for (i = 0; i < c->noutput; i++)
|
|
{
|
|
outputs[noutput] = dmxRRGetOutput (pScreen, dmxScreen, c->outputs[i]);
|
|
if (outputs[noutput])
|
|
noutput++;
|
|
}
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
gamma = XRRGetCrtcGamma (dmxScreen->beDisplay, xcrtc);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!gamma)
|
|
{
|
|
if (mode)
|
|
RRModeDestroy (mode);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
RRCrtcGammaSet (crtc, gamma->red, gamma->green, gamma->blue);
|
|
|
|
XRRFreeGamma (gamma);
|
|
|
|
RRCrtcNotify (crtc, mode, c->x, c->y, c->rotation, noutput, outputs);
|
|
|
|
if (outputs)
|
|
xfree (outputs);
|
|
|
|
if (mode)
|
|
RRModeDestroy (mode);
|
|
|
|
XRRFreeCrtcInfo (c);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRUpdateOutput (ScreenPtr pScreen,
|
|
DMXScreenInfo *dmxScreen,
|
|
XRRScreenResources *r,
|
|
unsigned long xoutput)
|
|
{
|
|
XRROutputInfo *o = NULL;
|
|
RROutputPtr output, *clones = NULL;
|
|
RRModePtr *modes = NULL;
|
|
RRCrtcPtr *crtcs = NULL;
|
|
int i, nclone = 0, ncrtc = 0;
|
|
|
|
output = dmxRRGetOutput (pScreen, dmxScreen, xoutput);
|
|
if (!output)
|
|
return TRUE; /* do nothing if the output doesn't exist */
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
o = XRRGetOutputInfo (dmxScreen->beDisplay, r, xoutput);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!o)
|
|
return FALSE;
|
|
|
|
if (o->nclone)
|
|
{
|
|
clones = xalloc (sizeof (RROutputPtr) * o->nclone);
|
|
if (!clones)
|
|
return FALSE;
|
|
}
|
|
|
|
if (o->nmode)
|
|
{
|
|
modes = xalloc (sizeof (RRModePtr) * o->nmode);
|
|
if (!modes)
|
|
return FALSE;
|
|
}
|
|
|
|
if (o->ncrtc)
|
|
{
|
|
crtcs = xalloc (sizeof (RRCrtcPtr) * o->ncrtc);
|
|
if (!crtcs)
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < o->nclone; i++)
|
|
{
|
|
clones[nclone] = dmxRRGetOutput (pScreen, dmxScreen, o->clones[i]);
|
|
if (clones[nclone])
|
|
nclone++;
|
|
}
|
|
|
|
for (i = 0; i < o->ncrtc; i++)
|
|
{
|
|
crtcs[ncrtc] = dmxRRGetCrtc (pScreen, dmxScreen, o->crtcs[i]);
|
|
if (crtcs[ncrtc])
|
|
ncrtc++;
|
|
}
|
|
|
|
for (i = 0; i < o->nmode; i++)
|
|
{
|
|
modes[i] = dmxRRGetMode (r, o->modes[i]);
|
|
if (!modes[i])
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RROutputSetClones (output, clones, nclone))
|
|
return FALSE;
|
|
|
|
if (!RROutputSetModes (output, modes, o->nmode, o->npreferred))
|
|
return FALSE;
|
|
|
|
if (!RROutputSetCrtcs (output, crtcs, ncrtc))
|
|
return FALSE;
|
|
|
|
if (!RROutputSetConnection (output, o->connection))
|
|
return FALSE;
|
|
|
|
if (!RROutputSetSubpixelOrder (output, o->subpixel_order))
|
|
return FALSE;
|
|
|
|
if (!RROutputSetPhysicalSize (output, o->mm_width, o->mm_height))
|
|
return FALSE;
|
|
|
|
if (clones)
|
|
xfree (clones);
|
|
|
|
if (modes)
|
|
xfree (modes);
|
|
|
|
if (crtcs)
|
|
xfree (crtcs);
|
|
|
|
XRRFreeOutputInfo (o);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRUpdateOutputProperty (ScreenPtr pScreen,
|
|
DMXScreenInfo *dmxScreen,
|
|
XRRScreenResources *r,
|
|
unsigned long xoutput,
|
|
unsigned long xproperty)
|
|
{
|
|
RROutputPtr output;
|
|
XRRPropertyInfo *info = NULL;
|
|
unsigned char *prop;
|
|
int format, status = !Success;
|
|
unsigned long nElements, bytesAfter;
|
|
Atom type, atom;
|
|
INT32 *values = NULL;
|
|
|
|
output = dmxRRGetOutput (pScreen, dmxScreen, xoutput);
|
|
if (!output)
|
|
return TRUE; /* do nothing if the output doesn't exist */
|
|
|
|
atom = dmxAtom (dmxScreen, xproperty);
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
status = XRRGetOutputProperty (dmxScreen->beDisplay, xoutput, xproperty,
|
|
0, 8192, FALSE, FALSE,
|
|
AnyPropertyType, &type, &format,
|
|
&nElements, &bytesAfter, &prop);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (status != Success)
|
|
return FALSE;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
info = XRRQueryOutputProperty (dmxScreen->beDisplay, xoutput, xproperty);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!info)
|
|
return FALSE;
|
|
|
|
if (info->num_values)
|
|
{
|
|
int i;
|
|
|
|
values = xalloc (info->num_values * sizeof (INT32));
|
|
if (!values)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < info->num_values; i++)
|
|
values[i] = info->values[i];
|
|
}
|
|
|
|
if (type == XA_ATOM && format == 32)
|
|
{
|
|
INT32 *atoms = (INT32 *) prop;
|
|
int i;
|
|
|
|
for (i = 0; i < nElements; i++)
|
|
atoms[i] = dmxAtom (dmxScreen, atoms[i]);
|
|
|
|
if (!info->range && info->num_values > 0)
|
|
{
|
|
for (i = 0; i < info->num_values; i++)
|
|
values[i] = dmxAtom (dmxScreen, values[i]);
|
|
}
|
|
}
|
|
|
|
RRConfigureOutputProperty (output, atom, FALSE,
|
|
info->range, info->immutable, info->num_values,
|
|
values);
|
|
|
|
RRChangeOutputProperty (output, atom, type, format, PropModeReplace,
|
|
nElements, prop, FALSE, TRUE);
|
|
|
|
if (values)
|
|
xfree (values);
|
|
|
|
XFree (info);
|
|
XFree (prop);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRGetInfo (ScreenPtr pScreen,
|
|
Rotation *rotations)
|
|
{
|
|
int i;
|
|
|
|
rrScrPriv (pScreen);
|
|
|
|
if (pScreen->myNum)
|
|
{
|
|
*rotations = RR_Rotate_0;
|
|
return TRUE;
|
|
}
|
|
|
|
for (i = 0; i < dmxNumScreens; i++)
|
|
{
|
|
DMXScreenInfo *dmxScreen = &dmxScreens[i];
|
|
XRRScreenResources *r = NULL;
|
|
int outputsPerScreen = xRROutputsForFirstScreen;
|
|
int baseOutput = 0;
|
|
int crtcsPerScreen = xRRCrtcsForFirstScreen;
|
|
int baseCrtc = 0;
|
|
int j;
|
|
|
|
if (i)
|
|
{
|
|
outputsPerScreen = xRROutputsPerScreen;
|
|
baseOutput = xRROutputsForFirstScreen +
|
|
(i - 1) * xRROutputsPerScreen;
|
|
crtcsPerScreen = xRRCrtcsPerScreen;
|
|
baseCrtc = xRRCrtcsForFirstScreen +
|
|
(i - 1) * xRRCrtcsPerScreen;
|
|
}
|
|
|
|
assert (baseOutput + outputsPerScreen <= pScrPriv->numOutputs);
|
|
assert (baseCrtc + crtcsPerScreen <= pScrPriv->numCrtcs);
|
|
|
|
dmxScreen->beRandrPending = TRUE;
|
|
|
|
if (dmxScreen->beRandr && dmxScreen->beDisplay)
|
|
{
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
r = XRRGetScreenResources (dmxScreen->beDisplay,
|
|
dmxScreen->scrnWin);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (r)
|
|
{
|
|
if (r->noutput > outputsPerScreen)
|
|
dmxLog (dmxWarning,
|
|
"dmxRRGetInfo: ignoring %d BE server outputs\n",
|
|
r->noutput - outputsPerScreen);
|
|
|
|
if (r->ncrtc > crtcsPerScreen)
|
|
dmxLog (dmxWarning,
|
|
"dmxRRGetInfo: ignoring %d BE server crtcs\n",
|
|
r->ncrtc - crtcsPerScreen);
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < outputsPerScreen; j++)
|
|
{
|
|
RROutputPtr output = pScrPriv->outputs[baseOutput + j];
|
|
|
|
if (r && j < r->noutput)
|
|
output->devPrivate = (void *) r->outputs[j];
|
|
else
|
|
output->devPrivate = NULL;
|
|
}
|
|
|
|
for (j = 0; j < crtcsPerScreen; j++)
|
|
{
|
|
RRCrtcPtr crtc = pScrPriv->crtcs[baseCrtc + j];
|
|
|
|
crtc->devPrivate = NULL;
|
|
|
|
if (r && j < r->ncrtc)
|
|
crtc->devPrivate = (void *) r->crtcs[j];
|
|
else
|
|
crtc->devPrivate = NULL;
|
|
}
|
|
|
|
for (j = 0; j < outputsPerScreen; j++)
|
|
{
|
|
RROutputPtr output = pScrPriv->outputs[baseOutput + j];
|
|
|
|
if (r)
|
|
{
|
|
if (j < r->noutput)
|
|
{
|
|
#ifdef _XSERVER64
|
|
Atom64 *props = NULL;
|
|
#else
|
|
Atom *props = NULL;
|
|
#endif
|
|
|
|
int nProp = 0, k;
|
|
|
|
if (!dmxRRUpdateOutput (pScreen,
|
|
dmxScreen,
|
|
r,
|
|
r->outputs[j]))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
props = XRRListOutputProperties (dmxScreen->beDisplay,
|
|
r->outputs[j],
|
|
&nProp);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (nProp)
|
|
{
|
|
for (k = 0; k < nProp; k++)
|
|
if (!dmxRRUpdateOutputProperty (pScreen,
|
|
dmxScreen,
|
|
r,
|
|
r->outputs[j],
|
|
props[k]))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
|
|
XFree (props);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!RROutputSetModes (output, NULL, 0, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetClones (output, NULL, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetCrtcs (output, NULL, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetConnection (output, RR_Disconnected))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
}
|
|
}
|
|
else if (dmxScreen->beDisplay && j == 0)
|
|
{
|
|
RRModePtr mode;
|
|
xRRModeInfo modeInfo;
|
|
char name[64];
|
|
|
|
sprintf (name,
|
|
"%dx%d",
|
|
dmxScreen->scrnWidth, dmxScreen->scrnHeight);
|
|
|
|
memset (&modeInfo, '\0', sizeof (modeInfo));
|
|
modeInfo.width = dmxScreen->scrnWidth;
|
|
modeInfo.height = dmxScreen->scrnHeight;
|
|
modeInfo.nameLength = strlen (name);
|
|
|
|
mode = RRModeGet (&modeInfo, name);
|
|
if (!mode)
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
|
|
if (!RROutputSetModes (output, &mode, 1, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetClones (output, NULL, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetCrtcs (output, &pScrPriv->crtcs[baseCrtc], 1))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetConnection (output, RR_Connected))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
}
|
|
else
|
|
{
|
|
if (!RROutputSetModes (output, NULL, 0, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetClones (output, NULL, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetCrtcs (output, NULL, 0))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
if (!RROutputSetConnection (output, RR_Disconnected))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
for (j = 0; j < crtcsPerScreen; j++)
|
|
{
|
|
RRCrtcPtr crtc = pScrPriv->crtcs[baseCrtc + j];
|
|
|
|
if (r)
|
|
{
|
|
if (j < r->ncrtc)
|
|
{
|
|
if (!dmxRRUpdateCrtc (pScreen, dmxScreen, r, r->crtcs[j]))
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
}
|
|
else
|
|
{
|
|
RRCrtcNotify (crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
|
|
}
|
|
}
|
|
else if (dmxScreen->beDisplay && j == 0)
|
|
{
|
|
RRModePtr mode;
|
|
xRRModeInfo modeInfo;
|
|
char name[64];
|
|
|
|
sprintf (name,
|
|
"%dx%d",
|
|
dmxScreen->scrnWidth, dmxScreen->scrnHeight);
|
|
|
|
memset (&modeInfo, '\0', sizeof (modeInfo));
|
|
modeInfo.width = dmxScreen->scrnWidth;
|
|
modeInfo.height = dmxScreen->scrnHeight;
|
|
modeInfo.nameLength = strlen (name);
|
|
|
|
mode = RRModeGet (&modeInfo, name);
|
|
if (!mode)
|
|
return (dmxScreen->beRandrPending = FALSE);
|
|
|
|
RRCrtcNotify (crtc, mode,
|
|
dmxScreen->rootX, dmxScreen->rootY,
|
|
RR_Rotate_0, 1,
|
|
&pScrPriv->outputs[baseOutput]);
|
|
|
|
if (mode)
|
|
RRModeDestroy (mode);
|
|
}
|
|
else
|
|
{
|
|
RRCrtcNotify (crtc, NULL, 0, 0, RR_Rotate_0, 0, NULL);
|
|
}
|
|
}
|
|
|
|
if (r)
|
|
XRRFreeScreenResources (r);
|
|
|
|
dmxScreen->beRandrPending = FALSE;
|
|
}
|
|
|
|
*rotations = RR_Rotate_0;
|
|
|
|
for (i = 0; i < pScrPriv->numCrtcs; i++)
|
|
*rotations |= pScrPriv->crtcs[i]->rotations;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static unsigned long
|
|
dmxRRGetXMode (XRRScreenResources *r,
|
|
RRModePtr mode)
|
|
{
|
|
xRRModeInfo modeInfo = mode->mode;
|
|
int i;
|
|
|
|
for (i = 0; i < r->nmode; i++)
|
|
{
|
|
if (modeInfo.width == r->modes[i].width &&
|
|
modeInfo.height == r->modes[i].height &&
|
|
modeInfo.dotClock == r->modes[i].dotClock &&
|
|
modeInfo.hSyncStart == r->modes[i].hSyncStart &&
|
|
modeInfo.hSyncEnd == r->modes[i].hSyncEnd &&
|
|
modeInfo.hTotal == r->modes[i].hTotal &&
|
|
modeInfo.hSkew == r->modes[i].hSkew &&
|
|
modeInfo.vSyncStart == r->modes[i].vSyncStart &&
|
|
modeInfo.vSyncEnd == r->modes[i].vSyncEnd &&
|
|
modeInfo.vTotal == r->modes[i].vTotal &&
|
|
modeInfo.nameLength == r->modes[i].nameLength &&
|
|
modeInfo.modeFlags == r->modes[i].modeFlags)
|
|
{
|
|
if (!memcmp (r->modes[i].name, mode->name, modeInfo.nameLength))
|
|
return r->modes[i].id;
|
|
}
|
|
}
|
|
|
|
return None;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRScreenSetSize (ScreenPtr pScreen,
|
|
CARD16 width,
|
|
CARD16 height,
|
|
CARD32 mmWidth,
|
|
CARD32 mmHeight)
|
|
{
|
|
|
|
#ifdef PANORAMIX
|
|
if (!noPanoramiXExtension)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < dmxNumScreens; i++)
|
|
dmxResizeRootWindow (WindowTable[i],
|
|
dmxScreens[i].rootX, dmxScreens[i].rootY,
|
|
width, height);
|
|
|
|
for (i = 0; i < dmxNumScreens; i++)
|
|
dmxUpdateScreenResources (screenInfo.screens[i],
|
|
0, 0, width, height);
|
|
|
|
dmxSetWidthHeight (width, height);
|
|
XineramaReinitData (pScreen);
|
|
dmxConnectionBlockCallback ();
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
dmxResizeRootWindow (WindowTable[pScreen->myNum],
|
|
dmxScreens[pScreen->myNum].rootX,
|
|
dmxScreens[pScreen->myNum].rootY,
|
|
width, height);
|
|
dmxUpdateScreenResources (pScreen, 0, 0, width, height);
|
|
}
|
|
|
|
pScreen->mmWidth = mmWidth;
|
|
pScreen->mmHeight = mmHeight;
|
|
|
|
RRScreenSizeNotify (pScreen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRRCrtcSet (ScreenPtr pScreen,
|
|
RRCrtcPtr crtc,
|
|
RRModePtr mode,
|
|
int x,
|
|
int y,
|
|
Rotation rotation,
|
|
int numOutputs,
|
|
RROutputPtr *outputs)
|
|
{
|
|
XRRScreenResources *r = NULL;
|
|
|
|
#ifdef _XSERVER64
|
|
RROutput64 *o = NULL;
|
|
#else
|
|
RROutput *o = NULL;
|
|
#endif
|
|
|
|
RRMode m = None;
|
|
Status status = !RRSetConfigSuccess;
|
|
int i;
|
|
DMXScreenInfo *dmxScreen;
|
|
|
|
dmxScreen = dmxRRGetScreenForCrtc (pScreen, crtc);
|
|
if (!dmxScreen)
|
|
return FALSE;
|
|
|
|
if (dmxScreen->beRandrPending)
|
|
return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
|
|
|
|
for (i = 0; i < numOutputs; i++)
|
|
if (!dmxRRGetOutput (pScreen,
|
|
dmxScreen,
|
|
(unsigned long) outputs[i]->devPrivate))
|
|
return FALSE;
|
|
|
|
if (numOutputs)
|
|
{
|
|
o = xalloc (sizeof (*o) * numOutputs);
|
|
if (!o)
|
|
return FALSE;
|
|
}
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
r = XRRGetScreenResources (dmxScreen->beDisplay,
|
|
DefaultRootWindow (dmxScreen->beDisplay));
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!r)
|
|
return FALSE;
|
|
|
|
if (mode)
|
|
{
|
|
m = dmxRRGetXMode (r, mode);
|
|
if (!m)
|
|
{
|
|
XRRFreeScreenResources (r);
|
|
if (o)
|
|
xfree (o);
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < numOutputs; i++)
|
|
o[i] = (unsigned long) outputs[i]->devPrivate;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
status = XRRSetCrtcConfig (dmxScreen->beDisplay, r,
|
|
(unsigned long) crtc->devPrivate,
|
|
CurrentTime,
|
|
x, y,
|
|
m,
|
|
rotation,
|
|
o, numOutputs);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
XRRFreeScreenResources (r);
|
|
|
|
if (o)
|
|
xfree (o);
|
|
|
|
if (status != RRSetConfigSuccess)
|
|
return FALSE;
|
|
|
|
return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs);
|
|
}
|
|
|
|
static Bool
|
|
dmxRRCrtcSetGamma (ScreenPtr pScreen,
|
|
RRCrtcPtr crtc)
|
|
{
|
|
XRRCrtcGamma *gamma;
|
|
DMXScreenInfo *dmxScreen;
|
|
|
|
dmxScreen = dmxRRGetScreenForCrtc (pScreen, crtc);
|
|
if (!dmxScreen)
|
|
return FALSE;
|
|
|
|
if (dmxScreen->beRandrPending)
|
|
return TRUE;
|
|
|
|
gamma = XRRAllocGamma (crtc->gammaSize);
|
|
if (!gamma)
|
|
return FALSE;
|
|
|
|
memcpy (gamma->red, crtc->gammaRed, gamma->size * sizeof (CARD16));
|
|
memcpy (gamma->green, crtc->gammaGreen, gamma->size * sizeof (CARD16));
|
|
memcpy (gamma->blue, crtc->gammaBlue, gamma->size * sizeof (CARD16));
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRSetCrtcGamma (dmxScreen->beDisplay, (unsigned long) crtc->devPrivate,
|
|
gamma);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
XRRFreeGamma (gamma);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRROutputSetProperty (ScreenPtr pScreen,
|
|
RROutputPtr output,
|
|
Atom property,
|
|
RRPropertyValuePtr value)
|
|
{
|
|
RRPropertyPtr p;
|
|
|
|
#ifdef _XSERVER64
|
|
Atom64 atom = 0, type = 0;
|
|
#else
|
|
Atom atom = 0, type = 0;
|
|
#endif
|
|
|
|
long *values = value->data;
|
|
long *validValues;
|
|
int i;
|
|
DMXScreenInfo *dmxScreen;
|
|
|
|
dmxScreen = dmxRRGetScreenForOutput (pScreen, output);
|
|
if (!dmxScreen)
|
|
return FALSE;
|
|
|
|
if (dmxScreen->beRandrPending)
|
|
return TRUE;
|
|
|
|
p = RRQueryOutputProperty (output, property);
|
|
if (!p)
|
|
return FALSE;
|
|
|
|
validValues = p->valid_values;
|
|
|
|
atom = dmxBEAtom (dmxScreen, property);
|
|
type = dmxBEAtom (dmxScreen, value->type);
|
|
|
|
if (type == XA_ATOM && value->format == 32)
|
|
{
|
|
INT32 *atoms = (INT32 *) value->data;
|
|
|
|
for (i = 0; i < value->size; i++)
|
|
if (!ValidAtom (atoms[i]))
|
|
return FALSE;
|
|
|
|
if (p->num_valid > 0)
|
|
{
|
|
for (i = 0; i < p->num_valid; i++)
|
|
if (!ValidAtom (p->valid_values[i]))
|
|
return FALSE;
|
|
|
|
for (i = 0; i < value->size; i++)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < p->num_valid; j++)
|
|
if (p->valid_values[j] == atoms[i])
|
|
break;
|
|
|
|
if (j == p->num_valid)
|
|
return FALSE;
|
|
}
|
|
|
|
validValues = xalloc (p->num_valid * sizeof (long));
|
|
if (!validValues)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < p->num_valid; i++)
|
|
validValues[i] = dmxBEAtom (dmxScreen, p->valid_values[i]);
|
|
}
|
|
|
|
if (value->size)
|
|
{
|
|
int size = value->size * (value->format / 8);
|
|
|
|
values = xalloc (size);
|
|
if (!values)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < value->size; i++)
|
|
values[i] = dmxBEAtom (dmxScreen, atoms[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (p->num_valid > 0)
|
|
{
|
|
validValues = xalloc (p->num_valid * sizeof (long));
|
|
if (!validValues)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < p->num_valid; i++)
|
|
validValues[i] = p->valid_values[i];
|
|
}
|
|
}
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRConfigureOutputProperty (dmxScreen->beDisplay,
|
|
(unsigned long) output->devPrivate,
|
|
atom, p->is_pending, p->range, p->num_valid,
|
|
validValues);
|
|
XRRChangeOutputProperty (dmxScreen->beDisplay,
|
|
(unsigned long) output->devPrivate,
|
|
atom, type, value->format, PropModeReplace,
|
|
(unsigned char *) values, value->size);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (validValues != p->valid_values)
|
|
xfree (validValues);
|
|
|
|
if (values != value->data)
|
|
xfree (values);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static Bool
|
|
dmxRROutputValidateMode (ScreenPtr pScreen,
|
|
RROutputPtr output,
|
|
RRModePtr mode)
|
|
{
|
|
XRRModeInfo *modeInfo;
|
|
|
|
#ifdef _XSERVER64
|
|
RRMode64 m = 0;
|
|
#else
|
|
RRMode m = 0;
|
|
#endif
|
|
|
|
DMXScreenInfo *dmxScreen;
|
|
|
|
dmxScreen = dmxRRGetScreenForOutput (pScreen, output);
|
|
if (!dmxScreen)
|
|
return FALSE;
|
|
|
|
if (dmxScreen->beRandrPending)
|
|
return TRUE;
|
|
|
|
modeInfo = XRRAllocModeInfo (mode->name, mode->mode.nameLength);
|
|
if (!modeInfo)
|
|
return FALSE;
|
|
|
|
modeInfo->width = mode->mode.width;
|
|
modeInfo->height = mode->mode.height;
|
|
modeInfo->dotClock = mode->mode.dotClock;
|
|
modeInfo->hSyncStart = mode->mode.hSyncStart;
|
|
modeInfo->hSyncEnd = mode->mode.hSyncEnd;
|
|
modeInfo->hTotal = mode->mode.hTotal;
|
|
modeInfo->hSkew = mode->mode.hSkew;
|
|
modeInfo->vSyncStart = mode->mode.vSyncStart;
|
|
modeInfo->vSyncEnd = mode->mode.vSyncEnd;
|
|
modeInfo->vTotal = mode->mode.vTotal;
|
|
modeInfo->modeFlags = mode->mode.modeFlags;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
m = XRRCreateMode (dmxScreen->beDisplay,
|
|
DefaultRootWindow (dmxScreen->beDisplay),
|
|
modeInfo);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (!m)
|
|
return FALSE;
|
|
|
|
XRRFreeModeInfo (modeInfo);
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRAddOutputMode (dmxScreen->beDisplay,
|
|
(unsigned long) output->devPrivate, m);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
dmxRRModeDestroy (ScreenPtr pScreen,
|
|
RRModePtr mode)
|
|
{
|
|
XRRScreenResources *r;
|
|
int i;
|
|
|
|
for (i = 0; i < dmxNumScreens; i++)
|
|
{
|
|
DMXScreenInfo *dmxScreen = &dmxScreens[i];
|
|
|
|
if (!dmxScreen->beRandr)
|
|
continue;
|
|
|
|
if (dmxScreen->beRandrPending)
|
|
continue;
|
|
|
|
r = NULL;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
r = XRRGetScreenResources (dmxScreen->beDisplay, dmxScreen->scrnWin);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (r)
|
|
{
|
|
|
|
#ifdef _XSERVER64
|
|
RRMode64 m;
|
|
#else
|
|
RRMode m;
|
|
#endif
|
|
|
|
m = dmxRRGetXMode (r, mode);
|
|
if (m)
|
|
{
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRDestroyMode (dmxScreen->beDisplay, m);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
}
|
|
|
|
XRRFreeScreenResources (r);
|
|
}
|
|
}
|
|
}
|
|
|
|
Bool
|
|
dmxScreenEventCheckRR (ScreenPtr pScreen,
|
|
xcb_generic_event_t *event)
|
|
{
|
|
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
|
|
|
switch (event->response_type & ~0x80) {
|
|
case XCB_MAP_NOTIFY:
|
|
if (((xcb_map_notify_event_t *) event)->window == dmxScreen->rootWin)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
case XCB_CONFIGURE_NOTIFY: {
|
|
xcb_configure_notify_event_t *xconfigure =
|
|
(xcb_configure_notify_event_t *) event;
|
|
XEvent X;
|
|
|
|
if (xconfigure->window == dmxScreen->scrnWin)
|
|
{
|
|
if (dmxScreen->scrnWidth == xconfigure->width &&
|
|
dmxScreen->scrnHeight == xconfigure->height)
|
|
return TRUE;
|
|
|
|
dmxScreen->scrnWidth = xconfigure->width;
|
|
dmxScreen->scrnHeight = xconfigure->height;
|
|
}
|
|
else if (xconfigure->window == dmxScreen->rootWin)
|
|
{
|
|
if (dmxScreen->rootX == xconfigure->x &&
|
|
dmxScreen->rootY == xconfigure->y)
|
|
return TRUE;
|
|
|
|
dmxScreen->rootX = xconfigure->x;
|
|
dmxScreen->rootY = xconfigure->y;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
X.xconfigure.type = XCB_CONFIGURE_NOTIFY;
|
|
X.xconfigure.display = dmxScreen->beDisplay;
|
|
X.xconfigure.window = xconfigure->window;
|
|
X.xconfigure.width = xconfigure->width;
|
|
X.xconfigure.height = xconfigure->height;
|
|
|
|
XRRUpdateConfiguration (&X);
|
|
} break;
|
|
default:
|
|
if (!dmxScreen->beRandr)
|
|
return FALSE;
|
|
|
|
switch ((event->response_type & ~0x80) - dmxScreen->beRandrEventBase) {
|
|
case XCB_RANDR_SCREEN_CHANGE_NOTIFY: {
|
|
xcb_randr_screen_change_notify_event_t *scevent =
|
|
(xcb_randr_screen_change_notify_event_t *) event;
|
|
XRRScreenChangeNotifyEvent X;
|
|
|
|
X.type = event->response_type;
|
|
X.display = dmxScreen->beDisplay;
|
|
X.root = scevent->root;
|
|
X.width = scevent->width;
|
|
X.mwidth = scevent->mwidth;
|
|
X.height = scevent->height;
|
|
X.mheight = scevent->mheight;
|
|
X.rotation = scevent->rotation;
|
|
X.subpixel_order = scevent->subpixel_order;
|
|
|
|
XRRUpdateConfiguration ((XEvent *) &X);
|
|
} break;
|
|
case XCB_RANDR_NOTIFY:
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
dmxScreen->beWidth =
|
|
DisplayWidth (dmxScreen->beDisplay,
|
|
DefaultScreen (dmxScreen->beDisplay));
|
|
dmxScreen->beHeight =
|
|
DisplayHeight (dmxScreen->beDisplay,
|
|
DefaultScreen (dmxScreen->beDisplay));
|
|
|
|
/* only call RRGetInfo when server is fully initialized */
|
|
if (dmxScreens[0].inputOverlayWid)
|
|
RRGetInfo (screenInfo.screens[0]);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
dmxRRScreenInit (ScreenPtr pScreen)
|
|
{
|
|
rrScrPrivPtr pScrPriv;
|
|
|
|
if (!RRScreenInit (pScreen))
|
|
return FALSE;
|
|
|
|
pScrPriv = rrGetScrPriv (pScreen);
|
|
pScrPriv->rrGetInfo = dmxRRGetInfo;
|
|
pScrPriv->rrScreenSetSize = dmxRRScreenSetSize;
|
|
pScrPriv->rrCrtcSet = dmxRRCrtcSet;
|
|
pScrPriv->rrCrtcSetGamma = dmxRRCrtcSetGamma;
|
|
pScrPriv->rrOutputSetProperty = dmxRROutputSetProperty;
|
|
pScrPriv->rrOutputValidateMode = dmxRROutputValidateMode;
|
|
pScrPriv->rrModeDestroy = dmxRRModeDestroy;
|
|
|
|
RRScreenSetSizeRange (pScreen, 1, 1, SHRT_MAX, SHRT_MAX);
|
|
|
|
if (pScreen->myNum)
|
|
{
|
|
char name[64];
|
|
int i;
|
|
|
|
for (i = 0; i < xRROutputsPerScreen; i++)
|
|
{
|
|
sprintf (name,
|
|
"dmx%d",
|
|
(pScreen->myNum - 1) * xRROutputsPerScreen + i);
|
|
|
|
if (!RROutputCreate (screenInfo.screens[0],
|
|
name,
|
|
strlen (name),
|
|
NULL))
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < xRRCrtcsPerScreen; i++)
|
|
if (!RRCrtcCreate (screenInfo.screens[0], NULL))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
XRRScreenResources *r = NULL;
|
|
DMXScreenInfo *dmxScreen = dmxScreens;
|
|
Display *display = dmxScreen->beDisplay;
|
|
Bool beRandr = FALSE;
|
|
|
|
if (display && dmxScreen->scrnWin == DefaultRootWindow (display))
|
|
{
|
|
int major, minor, status = 0;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
status = XRRQueryVersion (display, &major, &minor);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (status)
|
|
{
|
|
if (major > 1 || (major == 1 && minor >= 2))
|
|
{
|
|
int ignore;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
beRandr = XRRQueryExtension (display, &ignore, &ignore);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (display && beRandr)
|
|
{
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
r = XRRGetScreenResources (display, DefaultRootWindow (display));
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
}
|
|
|
|
if (r)
|
|
{
|
|
int i;
|
|
|
|
xRROutputsForFirstScreen = r->noutput;
|
|
xRRCrtcsForFirstScreen = r->ncrtc;
|
|
|
|
for (i = 0; i < r->noutput; i++)
|
|
{
|
|
XRROutputInfo *o;
|
|
|
|
o = XRRGetOutputInfo (display, r, r->outputs[i]);
|
|
if (!o)
|
|
return FALSE;
|
|
|
|
if (!RROutputCreate (screenInfo.screens[0],
|
|
o->name, strlen (o->name),
|
|
NULL))
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < r->ncrtc; i++)
|
|
if (!RRCrtcCreate (screenInfo.screens[0], NULL))
|
|
return FALSE;
|
|
|
|
XRRFreeScreenResources (r);
|
|
}
|
|
else
|
|
{
|
|
if (!RROutputCreate (screenInfo.screens[0], "default", 7, NULL))
|
|
return FALSE;
|
|
|
|
if (!RRCrtcCreate (screenInfo.screens[0], NULL))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
dmxBERRScreenInit (ScreenPtr pScreen)
|
|
{
|
|
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
|
|
|
dmxScreen->beRandr = FALSE;
|
|
|
|
if (dmxScreen->scrnWin == DefaultRootWindow (dmxScreen->beDisplay))
|
|
{
|
|
int major, minor, status = 0;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
status = XRRQueryVersion (dmxScreen->beDisplay, &major, &minor);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
if (status)
|
|
{
|
|
if (major > 1 || (major == 1 && minor >= 2))
|
|
{
|
|
int ignore;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
dmxScreen->beRandr =
|
|
XRRQueryExtension (dmxScreen->beDisplay,
|
|
&dmxScreen->beRandrEventBase,
|
|
&ignore);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
dmxLog (dmxInfo, "RandR 1.2 is present\n");
|
|
}
|
|
else
|
|
{
|
|
dmxLog (dmxInfo, "RandR 1.2 is not present\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dmxLog (dmxInfo, "RandR extension missing\n");
|
|
}
|
|
}
|
|
|
|
if (!dmxScreen->beRandr)
|
|
return FALSE;
|
|
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRSelectInput (dmxScreen->beDisplay,
|
|
DefaultRootWindow (dmxScreen->beDisplay),
|
|
RRScreenChangeNotifyMask |
|
|
RRCrtcChangeNotifyMask |
|
|
RROutputChangeNotifyMask |
|
|
RROutputPropertyNotifyMask);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
dmxBERRScreenFini (ScreenPtr pScreen)
|
|
{
|
|
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
|
|
|
if (dmxScreen->beRandr)
|
|
{
|
|
XLIB_PROLOGUE (dmxScreen);
|
|
XRRSelectInput (dmxScreen->beDisplay,
|
|
DefaultRootWindow (dmxScreen->beDisplay),
|
|
0);
|
|
XLIB_EPILOGUE (dmxScreen);
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|