952 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			952 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * 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"
 | 
						|
#include "swaprep.h"
 | 
						|
#include "registry.h"
 | 
						|
 | 
						|
RESTYPE	RRCrtcType;
 | 
						|
 | 
						|
/*
 | 
						|
 * Notify the CRTC of some change
 | 
						|
 */
 | 
						|
void
 | 
						|
RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
 | 
						|
{
 | 
						|
    ScreenPtr	pScreen = crtc->pScreen;
 | 
						|
 | 
						|
    crtc->changed = TRUE;
 | 
						|
    if (pScreen)
 | 
						|
    {
 | 
						|
	rrScrPriv(pScreen);
 | 
						|
    
 | 
						|
	pScrPriv->changed = TRUE;
 | 
						|
	/*
 | 
						|
	 * Send ConfigureNotify on any layout change
 | 
						|
	 */
 | 
						|
	if (layoutChanged)
 | 
						|
	    pScrPriv->layoutChanged = TRUE;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Create a CRTC
 | 
						|
 */
 | 
						|
RRCrtcPtr
 | 
						|
RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
 | 
						|
{
 | 
						|
    RRCrtcPtr	    crtc;
 | 
						|
    RRCrtcPtr	    *crtcs;
 | 
						|
    rrScrPrivPtr    pScrPriv;
 | 
						|
 | 
						|
    if (!RRInit())
 | 
						|
	return NULL;
 | 
						|
    
 | 
						|
    pScrPriv = rrGetScrPriv(pScreen);
 | 
						|
 | 
						|
    /* 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;
 | 
						|
    pScrPriv->crtcs = crtcs;
 | 
						|
    
 | 
						|
    crtc = xcalloc (1, sizeof (RRCrtcRec));
 | 
						|
    if (!crtc)
 | 
						|
	return NULL;
 | 
						|
    crtc->id = FakeClientID (0);
 | 
						|
    crtc->pScreen = pScreen;
 | 
						|
    crtc->mode = NULL;
 | 
						|
    crtc->x = 0;
 | 
						|
    crtc->y = 0;
 | 
						|
    crtc->rotation = RR_Rotate_0;
 | 
						|
    crtc->rotations = RR_Rotate_0;
 | 
						|
    crtc->outputs = NULL;
 | 
						|
    crtc->numOutputs = 0;
 | 
						|
    crtc->gammaSize = 0;
 | 
						|
    crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
 | 
						|
    crtc->changed = FALSE;
 | 
						|
    crtc->devPrivate = devPrivate;
 | 
						|
 | 
						|
    if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 | 
						|
	return NULL;
 | 
						|
 | 
						|
    /* attach the screen and crtc together */
 | 
						|
    crtc->pScreen = pScreen;
 | 
						|
    pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
 | 
						|
    
 | 
						|
    return crtc;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the allowed rotations on a CRTC
 | 
						|
 */
 | 
						|
void
 | 
						|
RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
 | 
						|
{
 | 
						|
    crtc->rotations = rotations;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Notify the extension that the Crtc has been reconfigured,
 | 
						|
 * the driver calls this whenever it has updated the mode
 | 
						|
 */
 | 
						|
Bool
 | 
						|
RRCrtcNotify (RRCrtcPtr	    crtc,
 | 
						|
	      RRModePtr	    mode,
 | 
						|
	      int	    x,
 | 
						|
	      int	    y,
 | 
						|
	      Rotation	    rotation,
 | 
						|
	      int	    numOutputs,
 | 
						|
	      RROutputPtr   *outputs)
 | 
						|
{
 | 
						|
    int	    i, j;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Check to see if any of the new outputs were
 | 
						|
     * not in the old list and mark them as changed
 | 
						|
     */
 | 
						|
    for (i = 0; i < numOutputs; i++)
 | 
						|
    {
 | 
						|
	for (j = 0; j < crtc->numOutputs; j++)
 | 
						|
	    if (outputs[i] == crtc->outputs[j])
 | 
						|
		break;
 | 
						|
	if (j == crtc->numOutputs)
 | 
						|
	{
 | 
						|
	    outputs[i]->crtc = crtc;
 | 
						|
	    RROutputChanged (outputs[i], FALSE);
 | 
						|
	    RRCrtcChanged (crtc, FALSE);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /*
 | 
						|
     * Check to see if any of the old outputs are
 | 
						|
     * not in the new list and mark them as changed
 | 
						|
     */
 | 
						|
    for (j = 0; j < crtc->numOutputs; j++)
 | 
						|
    {
 | 
						|
	for (i = 0; i < numOutputs; i++)
 | 
						|
	    if (outputs[i] == crtc->outputs[j])
 | 
						|
		break;
 | 
						|
	if (i == numOutputs)
 | 
						|
	{
 | 
						|
	    if (crtc->outputs[j]->crtc == crtc)
 | 
						|
		crtc->outputs[j]->crtc = NULL;
 | 
						|
	    RROutputChanged (crtc->outputs[j], FALSE);
 | 
						|
	    RRCrtcChanged (crtc, FALSE);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /*
 | 
						|
     * Reallocate the crtc output array if necessary
 | 
						|
     */
 | 
						|
    if (numOutputs != crtc->numOutputs)
 | 
						|
    {
 | 
						|
	RROutputPtr *newoutputs;
 | 
						|
	
 | 
						|
	if (numOutputs)
 | 
						|
	{
 | 
						|
	    if (crtc->numOutputs)
 | 
						|
		newoutputs = xrealloc (crtc->outputs,
 | 
						|
				    numOutputs * sizeof (RROutputPtr));
 | 
						|
	    else
 | 
						|
		newoutputs = xalloc (numOutputs * sizeof (RROutputPtr));
 | 
						|
	    if (!newoutputs)
 | 
						|
		return FALSE;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if (crtc->outputs)
 | 
						|
		xfree (crtc->outputs);
 | 
						|
	    newoutputs = NULL;
 | 
						|
	}
 | 
						|
	crtc->outputs = newoutputs;
 | 
						|
	crtc->numOutputs = numOutputs;
 | 
						|
    }
 | 
						|
    /*
 | 
						|
     * Copy the new list of outputs into the crtc
 | 
						|
     */
 | 
						|
    memcpy (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr));
 | 
						|
    /*
 | 
						|
     * Update remaining crtc fields
 | 
						|
     */
 | 
						|
    if (mode != crtc->mode)
 | 
						|
    {
 | 
						|
	if (crtc->mode)
 | 
						|
	    RRModeDestroy (crtc->mode);
 | 
						|
	crtc->mode = mode;
 | 
						|
	if (mode != NULL)
 | 
						|
	    mode->refcnt++;
 | 
						|
	RRCrtcChanged (crtc, TRUE);
 | 
						|
    }
 | 
						|
    if (x != crtc->x)
 | 
						|
    {
 | 
						|
	crtc->x = x;
 | 
						|
	RRCrtcChanged (crtc, TRUE);
 | 
						|
    }
 | 
						|
    if (y != crtc->y)
 | 
						|
    {
 | 
						|
	crtc->y = y;
 | 
						|
	RRCrtcChanged (crtc, TRUE);
 | 
						|
    }
 | 
						|
    if (rotation != crtc->rotation)
 | 
						|
    {
 | 
						|
	crtc->rotation = rotation;
 | 
						|
	RRCrtcChanged (crtc, TRUE);
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
 | 
						|
{
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    rrScrPriv (pScreen);
 | 
						|
    xRRCrtcChangeNotifyEvent	ce;
 | 
						|
    RRModePtr	mode = crtc->mode;
 | 
						|
    
 | 
						|
    ce.type = RRNotify + RREventBase;
 | 
						|
    ce.subCode = RRNotify_CrtcChange;
 | 
						|
    ce.sequenceNumber = client->sequence;
 | 
						|
    ce.timestamp = pScrPriv->lastSetTime.milliseconds;
 | 
						|
    ce.window = pWin->drawable.id;
 | 
						|
    ce.crtc = crtc->id;
 | 
						|
    ce.rotation = crtc->rotation;
 | 
						|
    if (mode)
 | 
						|
    {
 | 
						|
	ce.mode = mode->mode.id;
 | 
						|
	ce.x = crtc->x;
 | 
						|
	ce.y = crtc->y;
 | 
						|
	ce.width = mode->mode.width;
 | 
						|
	ce.height = mode->mode.height;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	ce.mode = None;
 | 
						|
	ce.x = 0;
 | 
						|
	ce.y = 0;
 | 
						|
	ce.width = 0;
 | 
						|
	ce.height = 0;
 | 
						|
    }
 | 
						|
    WriteEventsToClient (client, 1, (xEvent *) &ce);
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
RRCrtcPendingProperties (RRCrtcPtr crtc)
 | 
						|
{
 | 
						|
    ScreenPtr	pScreen = crtc->pScreen;
 | 
						|
    rrScrPriv(pScreen);
 | 
						|
    int		o;
 | 
						|
 | 
						|
    for (o = 0; o < pScrPriv->numOutputs; o++)
 | 
						|
    {
 | 
						|
	RROutputPtr output = pScrPriv->outputs[o];
 | 
						|
	if (output->crtc == crtc && output->pendingProperties)
 | 
						|
	    return TRUE;
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Request that the Crtc be reconfigured
 | 
						|
 */
 | 
						|
Bool
 | 
						|
RRCrtcSet (RRCrtcPtr    crtc,
 | 
						|
	   RRModePtr	mode,
 | 
						|
	   int		x,
 | 
						|
	   int		y,
 | 
						|
	   Rotation	rotation,
 | 
						|
	   int		numOutputs,
 | 
						|
	   RROutputPtr  *outputs)
 | 
						|
{
 | 
						|
    ScreenPtr	pScreen = crtc->pScreen;
 | 
						|
    Bool	ret = FALSE;
 | 
						|
    rrScrPriv(pScreen);
 | 
						|
 | 
						|
    /* See if nothing changed */
 | 
						|
    if (crtc->mode == mode &&
 | 
						|
	crtc->x == x &&
 | 
						|
	crtc->y == y &&
 | 
						|
	crtc->rotation == rotation &&
 | 
						|
	crtc->numOutputs == numOutputs &&
 | 
						|
	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
 | 
						|
	!RRCrtcPendingProperties (crtc))
 | 
						|
    {
 | 
						|
	ret = TRUE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
#if RANDR_12_INTERFACE
 | 
						|
	if (pScrPriv->rrCrtcSet)
 | 
						|
	{
 | 
						|
	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
 | 
						|
					  rotation, numOutputs, outputs);
 | 
						|
	}
 | 
						|
	else
 | 
						|
#endif
 | 
						|
	{
 | 
						|
#if RANDR_10_INTERFACE
 | 
						|
	    if (pScrPriv->rrSetConfig)
 | 
						|
	    {
 | 
						|
		RRScreenSize	    size;
 | 
						|
		RRScreenRate	    rate;
 | 
						|
 | 
						|
		if (!mode)
 | 
						|
		{
 | 
						|
		    RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
 | 
						|
		    ret = TRUE;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
		    size.width = mode->mode.width;
 | 
						|
		    size.height = mode->mode.height;
 | 
						|
		    if (outputs[0]->mmWidth && outputs[0]->mmHeight)
 | 
						|
		    {
 | 
						|
			size.mmWidth = outputs[0]->mmWidth;
 | 
						|
			size.mmHeight = outputs[0]->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);
 | 
						|
			RRScreenSizeNotify (pScreen);
 | 
						|
		    }
 | 
						|
		}
 | 
						|
	    }
 | 
						|
#endif
 | 
						|
	}
 | 
						|
	if (ret)
 | 
						|
	{
 | 
						|
	    int	o;
 | 
						|
	    RRTellChanged (pScreen);
 | 
						|
 | 
						|
	    for (o = 0; o < numOutputs; o++)
 | 
						|
		RRPostPendingProperties (outputs[o]);
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Destroy a Crtc at shutdown
 | 
						|
 */
 | 
						|
void
 | 
						|
RRCrtcDestroy (RRCrtcPtr crtc)
 | 
						|
{
 | 
						|
    FreeResource (crtc->id, 0);
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
RRCrtcDestroyResource (pointer value, XID pid)
 | 
						|
{
 | 
						|
    RRCrtcPtr	crtc = (RRCrtcPtr) value;
 | 
						|
    ScreenPtr	pScreen = crtc->pScreen;
 | 
						|
 | 
						|
    if (pScreen)
 | 
						|
    {
 | 
						|
	rrScrPriv(pScreen);
 | 
						|
	int		i;
 | 
						|
    
 | 
						|
	for (i = 0; i < pScrPriv->numCrtcs; i++)
 | 
						|
	{
 | 
						|
	    if (pScrPriv->crtcs[i] == crtc)
 | 
						|
	    {
 | 
						|
		memmove (pScrPriv->crtcs + i, pScrPriv->crtcs + i + 1,
 | 
						|
			 (pScrPriv->numCrtcs - (i + 1)) * sizeof (RRCrtcPtr));
 | 
						|
		--pScrPriv->numCrtcs;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    if (crtc->gammaRed)
 | 
						|
	xfree (crtc->gammaRed);
 | 
						|
    if (crtc->mode)
 | 
						|
	RRModeDestroy (crtc->mode);
 | 
						|
    xfree (crtc);
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Request that the Crtc gamma be changed
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
RRCrtcGammaSet (RRCrtcPtr   crtc,
 | 
						|
		CARD16	    *red,
 | 
						|
		CARD16	    *green,
 | 
						|
		CARD16	    *blue)
 | 
						|
{
 | 
						|
    Bool	ret = TRUE;
 | 
						|
#if RANDR_12_INTERFACE
 | 
						|
    ScreenPtr	pScreen = crtc->pScreen;
 | 
						|
#endif
 | 
						|
    
 | 
						|
    memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
 | 
						|
    memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
 | 
						|
    memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
 | 
						|
#if RANDR_12_INTERFACE
 | 
						|
    if (pScreen)
 | 
						|
    {
 | 
						|
	rrScrPriv(pScreen);
 | 
						|
	if (pScrPriv->rrCrtcSetGamma)
 | 
						|
	    ret = (*pScrPriv->rrCrtcSetGamma) (pScreen, crtc);
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Notify the extension that the Crtc gamma has been changed
 | 
						|
 * The driver calls this whenever it has changed the gamma values
 | 
						|
 * in the RRCrtcRec
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
RRCrtcGammaNotify (RRCrtcPtr	crtc)
 | 
						|
{
 | 
						|
    return TRUE;    /* not much going on here */
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Returns the width/height that the crtc scans out from the framebuffer
 | 
						|
 */
 | 
						|
void
 | 
						|
RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
 | 
						|
{
 | 
						|
    if (crtc->mode == NULL) {
 | 
						|
	*width = 0;
 | 
						|
	*height = 0;
 | 
						|
	return;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (crtc->rotation & 0xf) {
 | 
						|
    case RR_Rotate_0:
 | 
						|
    case RR_Rotate_180:
 | 
						|
	*width = crtc->mode->mode.width;
 | 
						|
	*height = crtc->mode->mode.height;
 | 
						|
	break;
 | 
						|
    case RR_Rotate_90:
 | 
						|
    case RR_Rotate_270:
 | 
						|
	*width = crtc->mode->mode.height;
 | 
						|
	*height = crtc->mode->mode.width;
 | 
						|
	break;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Set the size of the gamma table at server startup time
 | 
						|
 */
 | 
						|
 | 
						|
Bool
 | 
						|
RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 | 
						|
		    int		size)
 | 
						|
{
 | 
						|
    CARD16  *gamma;
 | 
						|
 | 
						|
    if (size == crtc->gammaSize)
 | 
						|
	return TRUE;
 | 
						|
    if (size)
 | 
						|
    {
 | 
						|
	gamma = xalloc (size * 3 * sizeof (CARD16));
 | 
						|
	if (!gamma)
 | 
						|
	    return FALSE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	gamma = NULL;
 | 
						|
    if (crtc->gammaRed)
 | 
						|
	xfree (crtc->gammaRed);
 | 
						|
    crtc->gammaRed = gamma;
 | 
						|
    crtc->gammaGreen = gamma + size;
 | 
						|
    crtc->gammaBlue = gamma + size*2;
 | 
						|
    crtc->gammaSize = size;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Initialize crtc type
 | 
						|
 */
 | 
						|
Bool
 | 
						|
RRCrtcInit (void)
 | 
						|
{
 | 
						|
    RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource);
 | 
						|
    if (!RRCrtcType)
 | 
						|
	return FALSE;
 | 
						|
    RegisterResourceName (RRCrtcType, "CRTC");
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRGetCrtcInfo (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRGetCrtcInfoReq);
 | 
						|
    xRRGetCrtcInfoReply	rep;
 | 
						|
    RRCrtcPtr			crtc;
 | 
						|
    CARD8			*extra;
 | 
						|
    unsigned long		extraLen;
 | 
						|
    ScreenPtr			pScreen;
 | 
						|
    rrScrPrivPtr		pScrPriv;
 | 
						|
    RRModePtr			mode;
 | 
						|
    RROutput			*outputs;
 | 
						|
    RROutput			*possible;
 | 
						|
    int				i, j, k, n;
 | 
						|
    int				width, height;
 | 
						|
    
 | 
						|
    REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
 | 
						|
    crtc = LookupCrtc(client, stuff->crtc, DixReadAccess);
 | 
						|
 | 
						|
    if (!crtc)
 | 
						|
	return RRErrorBase + BadRRCrtc;
 | 
						|
 | 
						|
    /* All crtcs must be associated with screens before client
 | 
						|
     * requests are processed
 | 
						|
     */
 | 
						|
    pScreen = crtc->pScreen;
 | 
						|
    pScrPriv = rrGetScrPriv(pScreen);
 | 
						|
 | 
						|
    mode = crtc->mode;
 | 
						|
    
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.status = RRSetConfigSuccess;
 | 
						|
    rep.sequenceNumber = client->sequence;
 | 
						|
    rep.length = 0;
 | 
						|
    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
 | 
						|
    rep.x = crtc->x;
 | 
						|
    rep.y = crtc->y;
 | 
						|
    RRCrtcGetScanoutSize (crtc, &width, &height);
 | 
						|
    rep.width = width;
 | 
						|
    rep.height = height;
 | 
						|
    rep.mode = mode ? mode->mode.id : 0;
 | 
						|
    rep.rotation = crtc->rotation;
 | 
						|
    rep.rotations = crtc->rotations;
 | 
						|
    rep.nOutput = crtc->numOutputs;
 | 
						|
    k = 0;
 | 
						|
    for (i = 0; i < pScrPriv->numOutputs; i++)
 | 
						|
	for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
 | 
						|
	    if (pScrPriv->outputs[i]->crtcs[j] == crtc)
 | 
						|
		k++;
 | 
						|
    rep.nPossibleOutput = k;
 | 
						|
    
 | 
						|
    rep.length = rep.nOutput + rep.nPossibleOutput;
 | 
						|
 | 
						|
    extraLen = rep.length << 2;
 | 
						|
    if (extraLen)
 | 
						|
    {
 | 
						|
	extra = xalloc (extraLen);
 | 
						|
	if (!extra)
 | 
						|
	    return BadAlloc;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	extra = NULL;
 | 
						|
 | 
						|
    outputs = (RROutput *) extra;
 | 
						|
    possible = (RROutput *) (outputs + rep.nOutput);
 | 
						|
    
 | 
						|
    for (i = 0; i < crtc->numOutputs; i++)
 | 
						|
    {
 | 
						|
	outputs[i] = crtc->outputs[i]->id;
 | 
						|
	if (client->swapped)
 | 
						|
	    swapl (&outputs[i], n);
 | 
						|
    }
 | 
						|
    k = 0;
 | 
						|
    for (i = 0; i < pScrPriv->numOutputs; i++)
 | 
						|
	for (j = 0; j < pScrPriv->outputs[i]->numCrtcs; j++)
 | 
						|
	    if (pScrPriv->outputs[i]->crtcs[j] == crtc)
 | 
						|
	    {
 | 
						|
		possible[k] = pScrPriv->outputs[i]->id;
 | 
						|
		if (client->swapped)
 | 
						|
		    swapl (&possible[k], n);
 | 
						|
		k++;
 | 
						|
	    }
 | 
						|
    
 | 
						|
    if (client->swapped) {
 | 
						|
	swaps(&rep.sequenceNumber, n);
 | 
						|
	swapl(&rep.length, n);
 | 
						|
	swapl(&rep.timestamp, n);
 | 
						|
	swaps(&rep.x, n);
 | 
						|
	swaps(&rep.y, n);
 | 
						|
	swaps(&rep.width, n);
 | 
						|
	swaps(&rep.height, n);
 | 
						|
	swapl(&rep.mode, n);
 | 
						|
	swaps(&rep.rotation, n);
 | 
						|
	swaps(&rep.rotations, n);
 | 
						|
	swaps(&rep.nOutput, n);
 | 
						|
	swaps(&rep.nPossibleOutput, n);
 | 
						|
    }
 | 
						|
    WriteToClient(client, sizeof(xRRGetCrtcInfoReply), (char *)&rep);
 | 
						|
    if (extraLen)
 | 
						|
    {
 | 
						|
	WriteToClient (client, extraLen, (char *) extra);
 | 
						|
	xfree (extra);
 | 
						|
    }
 | 
						|
    
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRSetCrtcConfig (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRSetCrtcConfigReq);
 | 
						|
    xRRSetCrtcConfigReply   rep;
 | 
						|
    ScreenPtr		    pScreen;
 | 
						|
    rrScrPrivPtr	    pScrPriv;
 | 
						|
    RRCrtcPtr		    crtc;
 | 
						|
    RRModePtr		    mode;
 | 
						|
    int			    numOutputs;
 | 
						|
    RROutputPtr		    *outputs = NULL;
 | 
						|
    RROutput		    *outputIds;
 | 
						|
    TimeStamp		    configTime;
 | 
						|
    TimeStamp		    time;
 | 
						|
    Rotation		    rotation;
 | 
						|
    int			    i, j;
 | 
						|
    
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
 | 
						|
    numOutputs = (stuff->length - (SIZEOF (xRRSetCrtcConfigReq) >> 2));
 | 
						|
    
 | 
						|
    crtc = LookupIDByType (stuff->crtc, RRCrtcType);
 | 
						|
    if (!crtc)
 | 
						|
    {
 | 
						|
	client->errorValue = stuff->crtc;
 | 
						|
	return RRErrorBase + BadRRCrtc;
 | 
						|
    }
 | 
						|
    if (stuff->mode == None)
 | 
						|
    {
 | 
						|
	mode = NULL;
 | 
						|
	if (numOutputs > 0)
 | 
						|
	    return BadMatch;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	mode = LookupIDByType (stuff->mode, RRModeType);
 | 
						|
	if (!mode)
 | 
						|
	{
 | 
						|
	    client->errorValue = stuff->mode;
 | 
						|
	    return RRErrorBase + BadRRMode;
 | 
						|
	}
 | 
						|
	if (numOutputs == 0)
 | 
						|
	    return BadMatch;
 | 
						|
    }
 | 
						|
    if (numOutputs)
 | 
						|
    {
 | 
						|
	outputs = xalloc (numOutputs * sizeof (RROutputPtr));
 | 
						|
	if (!outputs)
 | 
						|
	    return BadAlloc;
 | 
						|
    }
 | 
						|
    else
 | 
						|
	outputs = NULL;
 | 
						|
    
 | 
						|
    outputIds = (RROutput *) (stuff + 1);
 | 
						|
    for (i = 0; i < numOutputs; i++)
 | 
						|
    {
 | 
						|
	outputs[i] = (RROutputPtr) LookupIDByType (outputIds[i], RROutputType);
 | 
						|
	if (!outputs[i])
 | 
						|
	{
 | 
						|
	    client->errorValue = outputIds[i];
 | 
						|
	    if (outputs)
 | 
						|
		xfree (outputs);
 | 
						|
	    return RRErrorBase + BadRROutput;
 | 
						|
	}
 | 
						|
	/* validate crtc for this output */
 | 
						|
	for (j = 0; j < outputs[i]->numCrtcs; j++)
 | 
						|
	    if (outputs[i]->crtcs[j] == crtc)
 | 
						|
		break;
 | 
						|
	if (j == outputs[i]->numCrtcs)
 | 
						|
	{
 | 
						|
	    if (outputs)
 | 
						|
		xfree (outputs);
 | 
						|
	    return BadMatch;
 | 
						|
	}
 | 
						|
	/* validate mode for this output */
 | 
						|
	for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
 | 
						|
	{
 | 
						|
	    RRModePtr	m = (j < outputs[i]->numModes ? 
 | 
						|
			     outputs[i]->modes[j] :
 | 
						|
			     outputs[i]->userModes[j - outputs[i]->numModes]);
 | 
						|
	    if (m == mode)
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	if (j == outputs[i]->numModes + outputs[i]->numUserModes)
 | 
						|
	{
 | 
						|
	    if (outputs)
 | 
						|
		xfree (outputs);
 | 
						|
	    return BadMatch;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    /* validate clones */
 | 
						|
    for (i = 0; i < numOutputs; i++)
 | 
						|
    {
 | 
						|
	for (j = 0; j < numOutputs; j++)
 | 
						|
	{
 | 
						|
	    int k;
 | 
						|
	    if (i == j)
 | 
						|
		continue;
 | 
						|
	    for (k = 0; k < outputs[i]->numClones; k++)
 | 
						|
	    {
 | 
						|
		if (outputs[i]->clones[k] == outputs[j])
 | 
						|
		    break;
 | 
						|
	    }
 | 
						|
	    if (k == outputs[i]->numClones)
 | 
						|
	    {
 | 
						|
		if (outputs)
 | 
						|
		    xfree (outputs);
 | 
						|
		return BadMatch;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    pScreen = crtc->pScreen;
 | 
						|
    pScrPriv = rrGetScrPriv(pScreen);
 | 
						|
    
 | 
						|
    time = ClientTimeToServerTime(stuff->timestamp);
 | 
						|
    configTime = ClientTimeToServerTime(stuff->configTimestamp);
 | 
						|
    
 | 
						|
    if (!pScrPriv)
 | 
						|
    {
 | 
						|
	time = currentTime;
 | 
						|
	rep.status = RRSetConfigFailed;
 | 
						|
	goto sendReply;
 | 
						|
    }
 | 
						|
    
 | 
						|
#if 0
 | 
						|
    /*
 | 
						|
     * 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
 | 
						|
     * can't even be validated
 | 
						|
     */
 | 
						|
    if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
 | 
						|
    {
 | 
						|
	rep.status = RRSetConfigInvalidConfigTime;
 | 
						|
	goto sendReply;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Validate requested rotation
 | 
						|
     */
 | 
						|
    rotation = (Rotation) stuff->rotation;
 | 
						|
 | 
						|
    /* test the rotation bits only! */
 | 
						|
    switch (rotation & 0xf) {
 | 
						|
    case RR_Rotate_0:
 | 
						|
    case RR_Rotate_90:
 | 
						|
    case RR_Rotate_180:
 | 
						|
    case RR_Rotate_270:
 | 
						|
	break;
 | 
						|
    default:
 | 
						|
	/*
 | 
						|
	 * Invalid rotation
 | 
						|
	 */
 | 
						|
	client->errorValue = stuff->rotation;
 | 
						|
	if (outputs)
 | 
						|
	    xfree (outputs);
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mode)
 | 
						|
    {
 | 
						|
	if ((~crtc->rotations) & rotation)
 | 
						|
	{
 | 
						|
	    /*
 | 
						|
	     * requested rotation or reflection not supported by screen
 | 
						|
	     */
 | 
						|
	    client->errorValue = stuff->rotation;
 | 
						|
	    if (outputs)
 | 
						|
		xfree (outputs);
 | 
						|
	    return BadMatch;
 | 
						|
	}
 | 
						|
    
 | 
						|
#ifdef RANDR_12_INTERFACE
 | 
						|
	/*
 | 
						|
	 * Check screen size bounds if the DDX provides a 1.2 interface
 | 
						|
	 * for setting screen size. Else, assume the CrtcSet sets
 | 
						|
	 * the size along with the mode
 | 
						|
	 */
 | 
						|
	if (pScrPriv->rrScreenSetSize)
 | 
						|
	{
 | 
						|
	    int source_width = mode->mode.width;
 | 
						|
	    int	source_height = mode->mode.height;
 | 
						|
 | 
						|
	    if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270)
 | 
						|
	    {
 | 
						|
		source_width = mode->mode.height;
 | 
						|
		source_height = mode->mode.width;
 | 
						|
	    }
 | 
						|
	    if (stuff->x + source_width > pScreen->width)
 | 
						|
	    {
 | 
						|
		client->errorValue = stuff->x;
 | 
						|
		if (outputs)
 | 
						|
		    xfree (outputs);
 | 
						|
		return BadValue;
 | 
						|
	    }
 | 
						|
	    
 | 
						|
	    if (stuff->y + source_height > pScreen->height)
 | 
						|
	    {
 | 
						|
		client->errorValue = stuff->y;
 | 
						|
		if (outputs)
 | 
						|
		    xfree (outputs);
 | 
						|
		return BadValue;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
#endif
 | 
						|
    }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Make sure the requested set-time is not older than
 | 
						|
     * the last set-time
 | 
						|
     */
 | 
						|
    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
 | 
						|
    {
 | 
						|
	rep.status = RRSetConfigInvalidTime;
 | 
						|
	goto sendReply;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
 | 
						|
		   rotation, numOutputs, outputs))
 | 
						|
    {
 | 
						|
	rep.status = RRSetConfigFailed;
 | 
						|
	goto sendReply;
 | 
						|
    }
 | 
						|
    rep.status = RRSetConfigSuccess;
 | 
						|
    
 | 
						|
sendReply:
 | 
						|
    if (outputs)
 | 
						|
	xfree (outputs);
 | 
						|
    
 | 
						|
    rep.type = X_Reply;
 | 
						|
    /* rep.status has already been filled in */
 | 
						|
    rep.length = 0;
 | 
						|
    rep.sequenceNumber = client->sequence;
 | 
						|
    rep.newTimestamp = pScrPriv->lastConfigTime.milliseconds;
 | 
						|
 | 
						|
    if (client->swapped) 
 | 
						|
    {
 | 
						|
	int n;
 | 
						|
    	swaps(&rep.sequenceNumber, n);
 | 
						|
    	swapl(&rep.length, n);
 | 
						|
	swapl(&rep.newTimestamp, n);
 | 
						|
    }
 | 
						|
    WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
 | 
						|
    
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRGetCrtcGammaSize (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRGetCrtcGammaSizeReq);
 | 
						|
    xRRGetCrtcGammaSizeReply	reply;
 | 
						|
    RRCrtcPtr			crtc;
 | 
						|
    int				n;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH(xRRGetCrtcGammaSizeReq);
 | 
						|
    crtc = LookupCrtc (client, stuff->crtc, DixReadAccess);
 | 
						|
    if (!crtc)
 | 
						|
	return RRErrorBase + BadRRCrtc;
 | 
						|
    
 | 
						|
    reply.type = X_Reply;
 | 
						|
    reply.sequenceNumber = client->sequence;
 | 
						|
    reply.length = 0;
 | 
						|
    reply.size = crtc->gammaSize;
 | 
						|
    if (client->swapped) {
 | 
						|
	swaps (&reply.sequenceNumber, n);
 | 
						|
	swapl (&reply.length, n);
 | 
						|
	swaps (&reply.size, n);
 | 
						|
    }
 | 
						|
    WriteToClient (client, sizeof (xRRGetCrtcGammaSizeReply), (char *) &reply);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRGetCrtcGamma (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRGetCrtcGammaReq);
 | 
						|
    xRRGetCrtcGammaReply	reply;
 | 
						|
    RRCrtcPtr			crtc;
 | 
						|
    int				n;
 | 
						|
    unsigned long		len;
 | 
						|
    
 | 
						|
    REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
 | 
						|
    crtc = LookupCrtc (client, stuff->crtc, DixReadAccess);
 | 
						|
    if (!crtc)
 | 
						|
	return RRErrorBase + BadRRCrtc;
 | 
						|
    
 | 
						|
    len = crtc->gammaSize * 3 * 2;
 | 
						|
    
 | 
						|
    reply.type = X_Reply;
 | 
						|
    reply.sequenceNumber = client->sequence;
 | 
						|
    reply.length = (len + 3) >> 2;
 | 
						|
    reply.size = crtc->gammaSize;
 | 
						|
    if (client->swapped) {
 | 
						|
	swaps (&reply.sequenceNumber, n);
 | 
						|
	swapl (&reply.length, n);
 | 
						|
	swaps (&reply.size, n);
 | 
						|
    }
 | 
						|
    WriteToClient (client, sizeof (xRRGetCrtcGammaReply), (char *) &reply);
 | 
						|
    if (crtc->gammaSize)
 | 
						|
    {
 | 
						|
	client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write;
 | 
						|
	WriteSwappedDataToClient (client, len, (char *) crtc->gammaRed);
 | 
						|
    }
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ProcRRSetCrtcGamma (ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xRRSetCrtcGammaReq);
 | 
						|
    RRCrtcPtr			crtc;
 | 
						|
    unsigned long		len;
 | 
						|
    CARD16			*red, *green, *blue;
 | 
						|
    
 | 
						|
    REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
 | 
						|
    crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
 | 
						|
    if (!crtc)
 | 
						|
	return RRErrorBase + BadRRCrtc;
 | 
						|
    
 | 
						|
    len = client->req_len - (sizeof (xRRSetCrtcGammaReq) >> 2);
 | 
						|
    if (len < (stuff->size * 3 + 1) >> 1)
 | 
						|
	return BadLength;
 | 
						|
 | 
						|
    if (stuff->size != crtc->gammaSize)
 | 
						|
	return BadMatch;
 | 
						|
    
 | 
						|
    red = (CARD16 *) (stuff + 1);
 | 
						|
    green = red + crtc->gammaSize;
 | 
						|
    blue = green + crtc->gammaSize;
 | 
						|
    
 | 
						|
    RRCrtcGammaSet (crtc, red, green, blue);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 |