modesetting: Fix ms_covering_crtc() segfault with non-modesetting slave primary
ms_covering_crtc() uses RRFirstOutput() to determine a primary output to fall
back to if a drawable is overlapping a slave output.
If the primary output is a slave output, RRFirstOutput() will return a slave
output even if passed a master ScreenPtr. ms_covering_crtc() dereferences the
output's devPrivate, which is invalid for non-modesetting outputs, and can
crash.
Changing RRFirstOutput() could have unintended side effects for other callers,
so this change replaces the call to RRFirstOutput() with ms_first_output().
ms_first_output() ignores the primary output if it doesn't match the given
ScreenPtr, choosing the first connected output instead.
Signed-off-by: Alex Goins <agoins@nvidia.com>
(cherry picked from commit 3ef9029ace
)
This commit is contained in:
parent
2dd9dfc8d9
commit
341a478715
|
@ -90,6 +90,39 @@ ms_crtc_on(xf86CrtcPtr crtc)
|
||||||
return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
|
return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the first output which is connected to an active CRTC on this screen.
|
||||||
|
*
|
||||||
|
* RRFirstOutput() will return an output from a slave screen if it is primary,
|
||||||
|
* which is not the behavior that ms_covering_crtc() wants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static RROutputPtr ms_first_output(ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
RROutputPtr output;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if (!pScrPriv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc &&
|
||||||
|
(pScrPriv->primaryOutput->pScreen == pScreen)) {
|
||||||
|
return pScrPriv->primaryOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pScrPriv->numCrtcs; i++) {
|
||||||
|
RRCrtcPtr crtc = pScrPriv->crtcs[i];
|
||||||
|
|
||||||
|
for (j = 0; j < pScrPriv->numOutputs; j++) {
|
||||||
|
output = pScrPriv->outputs[j];
|
||||||
|
if (output->crtc == crtc)
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the crtc covering 'box'. If two crtcs cover a portion of
|
* Return the crtc covering 'box'. If two crtcs cover a portion of
|
||||||
* 'box', then prefer the crtc with greater coverage.
|
* 'box', then prefer the crtc with greater coverage.
|
||||||
|
@ -135,7 +168,7 @@ ms_covering_crtc(ScreenPtr pScreen, BoxPtr box, Bool screen_is_ms)
|
||||||
ScreenPtr slave;
|
ScreenPtr slave;
|
||||||
|
|
||||||
if (dixPrivateKeyRegistered(rrPrivKey))
|
if (dixPrivateKeyRegistered(rrPrivKey))
|
||||||
primary_output = RRFirstOutput(scrn->pScreen);
|
primary_output = ms_first_output(scrn->pScreen);
|
||||||
if (!primary_output || !primary_output->crtc)
|
if (!primary_output || !primary_output->crtc)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue