diff options
Diffstat (limited to 'randr/rrcrtc.c')
-rw-r--r-- | randr/rrcrtc.c | 147 |
1 files changed, 92 insertions, 55 deletions
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 39af679b2..338064f9f 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -1075,7 +1075,7 @@ ProcRRGetCrtcInfo(ClientPtr client) REQUEST(xRRGetCrtcInfoReq); xRRGetCrtcInfoReply rep; RRCrtcPtr crtc; - CARD8 *extra; + CARD8 *extra = NULL; unsigned long extraLen; ScreenPtr pScreen; rrScrPrivPtr pScrPriv; @@ -1085,10 +1085,13 @@ ProcRRGetCrtcInfo(ClientPtr client) int i, j, k; int width, height; BoxRec panned_area; + Bool leased; REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq); VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + leased = RRCrtcIsLeased(crtc); + /* All crtcs must be associated with screens before client * requests are processed */ @@ -1104,61 +1107,77 @@ ProcRRGetCrtcInfo(ClientPtr client) .length = 0, .timestamp = pScrPriv->lastSetTime.milliseconds }; - if (pScrPriv->rrGetPanning && - pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) && - (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) - { - rep.x = panned_area.x1; - rep.y = panned_area.y1; - rep.width = panned_area.x2 - panned_area.x1; - rep.height = panned_area.y2 - panned_area.y1; - } - else { - RRCrtcGetScanoutSize(crtc, &width, &height); - rep.x = crtc->x; - rep.y = crtc->y; - 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 = malloc(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]); - } - 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]); - k++; + if (leased) { + rep.x = rep.y = rep.width = rep.height = 0; + rep.mode = 0; + rep.rotation = RR_Rotate_0; + rep.rotations = RR_Rotate_0; + rep.nOutput = 0; + rep.nPossibleOutput = 0; + rep.length = 0; + extraLen = 0; + } else { + if (pScrPriv->rrGetPanning && + pScrPriv->rrGetPanning(pScreen, crtc, &panned_area, NULL, NULL) && + (panned_area.x2 > panned_area.x1) && (panned_area.y2 > panned_area.y1)) + { + rep.x = panned_area.x1; + rep.y = panned_area.y1; + rep.width = panned_area.x2 - panned_area.x1; + rep.height = panned_area.y2 - panned_area.y1; + } + else { + RRCrtcGetScanoutSize(crtc, &width, &height); + rep.x = crtc->x; + rep.y = crtc->y; + 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++) { + if (!RROutputIsLeased(pScrPriv->outputs[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 = malloc(extraLen); + if (!extra) + return BadAlloc; + } + + 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]); + } + k = 0; + for (i = 0; i < pScrPriv->numOutputs; i++) { + if (!RROutputIsLeased(pScrPriv->outputs[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]); + k++; + } } + } + } if (client->swapped) { swaps(&rep.sequenceNumber); @@ -1205,6 +1224,9 @@ ProcRRSetCrtcConfig(ClientPtr client) VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess); + if (RRCrtcIsLeased(crtc)) + return BadAccess; + if (stuff->mode == None) { mode = NULL; if (numOutputs > 0) @@ -1231,6 +1253,12 @@ ProcRRSetCrtcConfig(ClientPtr client) free(outputs); return ret; } + + if (RROutputIsLeased(outputs[i])) { + free(outputs); + return BadAccess; + } + /* validate crtc for this output */ for (j = 0; j < outputs[i]->numCrtcs; j++) if (outputs[i]->crtcs[j] == crtc) @@ -1474,6 +1502,9 @@ ProcRRSetPanning(ClientPtr client) REQUEST_SIZE_MATCH(xRRSetPanningReq); VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + if (RRCrtcIsLeased(crtc)) + return BadAccess; + /* All crtcs must be associated with screens before client * requests are processed */ @@ -1614,6 +1645,9 @@ ProcRRSetCrtcGamma(ClientPtr client) REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq); VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + if (RRCrtcIsLeased(crtc)) + return BadAccess; + len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcGammaReq)); if (len < (stuff->size * 3 + 1) >> 1) return BadLength; @@ -1647,6 +1681,9 @@ ProcRRSetCrtcTransform(ClientPtr client) REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq); VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess); + if (RRCrtcIsLeased(crtc)) + return BadAccess; + PictTransform_from_xRenderTransform(&transform, &stuff->transform); pixman_f_transform_from_pixman_transform(&f_transform, &transform); if (!pixman_f_transform_invert(&f_inverse, &f_transform)) |