int
ProcRRDeleteOutputMode (ClientPtr client)
{
    REQUEST(xRRDeleteOutputModeReq);
    RRModePtr	mode;
    RROutputPtr	output;

    REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
    VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
    VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);

    return RROutputDeleteUserMode (output, mode);
}
int
ProcRRDestroyMode (ClientPtr client)
{
    REQUEST(xRRDestroyModeReq);
    RRModePtr	mode;

    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
    VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);

    if (!mode->userScreen)
        return BadMatch;
    if (mode->refcnt > 1)
        return BadAccess;
    FreeResource (stuff->mode, 0);
    return Success;
}
Beispiel #3
0
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			    rc, i, j;
    
    REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
    numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq)));
    
    VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);

    if (stuff->mode == None)
    {
	mode = NULL;
	if (numOutputs > 0)
	    return BadMatch;
    }
    else
    {
	VERIFY_RR_MODE(stuff->mode, mode, DixSetAttrAccess);
	if (numOutputs == 0)
	    return BadMatch;
    }
    if (numOutputs)
    {
	outputs = malloc(numOutputs * sizeof (RROutputPtr));
	if (!outputs)
	    return BadAlloc;
    }
    else
	outputs = NULL;
    
    outputIds = (RROutput *) (stuff + 1);
    for (i = 0; i < numOutputs; i++)
    {
	rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
				     RROutputType, client, DixSetAttrAccess);
	if (rc != Success)
	{
	    free(outputs);
	    return rc;
	}
	/* 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)
	{
	    free(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)
	{
	    free(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)
	    {
		free(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;
    }
    
    /*
     * 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;
	free(outputs);
	return BadValue;
    }

    if (mode)
    {
	if ((~crtc->rotations) & rotation)
	{
	    /*
	     * requested rotation or reflection not supported by screen
	     */
	    client->errorValue = stuff->rotation;
	    free(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 the driver supports transforms,
	 * then it must allow crtcs to display a subset of the screen, so
	 * only do this check for drivers without transform support.
	 */
	if (pScrPriv->rrScreenSetSize && !crtc->transforms)
	{
	    int source_width;
	    int	source_height;
	    PictTransform transform;
	    struct pixman_f_transform f_transform, f_inverse;

	    RRTransformCompute (stuff->x, stuff->y,
				mode->mode.width, mode->mode.height,
				rotation,
				&crtc->client_pending_transform,
				&transform, &f_transform, &f_inverse);

	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
	    if (stuff->x + source_width > pScreen->width)
	    {
		client->errorValue = stuff->x;
		free(outputs);
		return BadValue;
	    }
	    
	    if (stuff->y + source_height > pScreen->height)
	    {
		client->errorValue = stuff->y;
		free(outputs);
		return BadValue;
	    }
	}
#endif
    }
    
    if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
		   rotation, numOutputs, outputs))
    {
	rep.status = RRSetConfigFailed;
	goto sendReply;
    }
    rep.status = RRSetConfigSuccess;
    pScrPriv->lastSetTime = time;
    
sendReply:
    free(outputs);
    
    rep.type = X_Reply;
    /* rep.status has already been filled in */
    rep.length = 0;
    rep.sequenceNumber = client->sequence;
    rep.newTimestamp = pScrPriv->lastSetTime.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 Success;
}
int
ProcRRCreateMode(ClientPtr client)
{
    REQUEST(xRRCreateModeReq);
    xRRCreateModeReply rep;
    WindowPtr pWin;
    ScreenPtr pScreen;
    xRRModeInfo *modeInfo;
    long units_after;
    char *name;
    int error, rc;
    RRModePtr mode;

    REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    if (rc != Success)
        return rc;

    pScreen = pWin->drawable.pScreen;

    modeInfo = &stuff->modeInfo;
    name = (char *) (stuff + 1);
    units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq)));

    /* check to make sure requested name fits within the data provided */
    if (bytes_to_int32(modeInfo->nameLength) > units_after)
        return BadLength;

    mode = RRModeCreateUser(pScreen, modeInfo, name, &error);
    if (!mode)
        return error;

    rep = (xRRCreateModeReply) {
        .type = X_Reply,
        .sequenceNumber = client->sequence,
        .length = 0,
        .mode = mode->mode.id
	};
    if (client->swapped) {
        swaps(&rep.sequenceNumber);
        swapl(&rep.length);
        swapl(&rep.mode);
    }
    WriteToClient(client, sizeof(xRRCreateModeReply), &rep);
    /* Drop out reference to this mode */
    RRModeDestroy(mode);
    return Success;
}

int
ProcRRDestroyMode(ClientPtr client)
{
    REQUEST(xRRDestroyModeReq);
    RRModePtr mode;

    REQUEST_SIZE_MATCH(xRRDestroyModeReq);
    VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);

    if (!mode->userScreen)
        return BadMatch;
    if (mode->refcnt > 1)
        return BadAccess;
    FreeResource(stuff->mode, 0);
    return Success;
}