[PATCH] randr: fix primary setting of slave outputs

Aaron Plattner aplattner at nvidia.com
Tue Mar 18 14:33:27 PDT 2014


On 02/20/2014 08:28 PM, Dave Airlie wrote:
> From: Fedora X Ninjas <x at fedoraproject.org>
>
> If the user wants to set one of the slave devices as
> the primary output, we shouldn't fail to do so,
> we were returning BadMatch which was tripping up
> gnome-settings-daemon and bad things ensues.
>
> Fix all the places we use primaryOutput to work
> out primaryCrtc and take it into a/c when slave
> gpus are in use.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>   randr/rroutput.c   |  6 +++++-
>   randr/rrscreen.c   | 22 ++++++++++++++++++----
>   randr/rrxinerama.c | 12 ++++++++++--
>   3 files changed, 33 insertions(+), 7 deletions(-)
>
> diff --git a/randr/rroutput.c b/randr/rroutput.c
> index f824f50..1649309 100644
> --- a/randr/rroutput.c
> +++ b/randr/rroutput.c
> @@ -540,7 +540,11 @@ ProcRRSetOutputPrimary(ClientPtr client)
>       if (stuff->output) {
>           VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
>
> -        if (output->pScreen != pWin->drawable.pScreen) {
> +        if (!output->pScreen->isGPU && output->pScreen != pWin->drawable.pScreen) {
> +            client->errorValue = stuff->window;
> +            return BadMatch;
> +        }
> +        if (output->pScreen->isGPU && output->pScreen->current_master != pWin->drawable.pScreen) {
>               client->errorValue = stuff->window;
>               return BadMatch;
>           }
> diff --git a/randr/rrscreen.c b/randr/rrscreen.c
> index 36179ae..47d1823 100644
> --- a/randr/rrscreen.c
> +++ b/randr/rrscreen.c
> @@ -322,8 +322,13 @@ static inline void swap_modeinfos(xRRModeInfo *modeinfos, int i)
>       swapl(&modeinfos[i].modeFlags);
>   }
>
> -#define update_arrays(gpuscreen, pScrPriv) do {            \
> +#define update_arrays(gpuscreen, pScrPriv, primary_crtc) do {            \
>       for (j = 0; j < pScrPriv->numCrtcs; j++) {             \
> +        if (has_primary && \
> +            primary_crtc == pScrPriv->crtcs[j]) { \
> +            has_primary = 0;   \

It's a little weird that has_primary is a magical parameter to this 
macro, but I don't have the energy to care today.  You could probably 
just drop that part though, since there should only ever be one primary 
crtc.

> +            continue; \
> +        }\
>           crtcs[crtc_count] = pScrPriv->crtcs[j]->id;        \
>           if (client->swapped)                               \
>               swapl(&crtcs[crtc_count]);                     \
> @@ -366,9 +371,11 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
>       unsigned long extraLen;
>       CARD8 *extra;
>       RRCrtc *crtcs;
> +    RRCrtcPtr primary_crtc = NULL;
>       RROutput *outputs;
>       xRRModeInfo *modeinfos;
>       CARD8 *names;
> +    int has_primary = 0;

Any reason to use int/0/1 instead of Bool/FALSE/TRUE here?

>
>       /* we need to iterate all the GPU masters and all their output slaves */
>       total_crtcs = 0;
> @@ -426,18 +433,25 @@ rrGetMultiScreenResources(ClientPtr client, Bool query, ScreenPtr pScreen)
>       modeinfos = (xRRModeInfo *)(outputs + total_outputs);
>       names = (CARD8 *)(modeinfos + total_modes);
>
> -    /* TODO primary */
>       crtc_count = 0;
>       output_count = 0;
>       mode_count = 0;
>
>       pScrPriv = rrGetScrPriv(pScreen);
> -    update_arrays(pScreen, pScrPriv);
> +    if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
> +        has_primary = 1;
> +	primary_crtc = pScrPriv->primaryOutput->crtc;

Indentation is screwy here, and it doesn't look like it's just the usual 
Exchange server brokenness this time.

> +        crtcs[0] = pScrPriv->primaryOutput->crtc->id;
> +        if (client->swapped)
> +            swapl(&crtcs[0]);
> +	crtc_count = 1;
> +    }
> +    update_arrays(pScreen, pScrPriv, primary_crtc);
>
>       xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
>           pScrPriv = rrGetScrPriv(iter);
>
> -        update_arrays(iter, pScrPriv);
> +        update_arrays(iter, pScrPriv, primary_crtc);
>       }
>
>       assert(bytes_to_int32((char *) names - (char *) extra) == rep.length);
> diff --git a/randr/rrxinerama.c b/randr/rrxinerama.c
> index 76d728c..363cead 100644
> --- a/randr/rrxinerama.c
> +++ b/randr/rrxinerama.c
> @@ -344,15 +344,17 @@ ProcRRXineramaQueryScreens(ClientPtr client)
>           ScreenPtr slave;
>           rrScrPriv(pScreen);
>           int has_primary = 0;
> +        RRCrtcPtr primary_crtc = NULL;
>
>           if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
>               has_primary = 1;
> +            primary_crtc = pScrPriv->primaryOutput->crtc;
>               RRXineramaWriteCrtc(client, pScrPriv->primaryOutput->crtc);
>           }
>
>           for (i = 0; i < pScrPriv->numCrtcs; i++) {
>               if (has_primary &&
> -                pScrPriv->primaryOutput->crtc == pScrPriv->crtcs[i]) {
> +                primary_crtc == pScrPriv->crtcs[i]) {
>                   has_primary = 0;
>                   continue;
>               }
> @@ -362,8 +364,14 @@ ProcRRXineramaQueryScreens(ClientPtr client)
>           xorg_list_for_each_entry(slave, &pScreen->output_slave_list, output_head) {
>               rrScrPrivPtr pSlavePriv;
>               pSlavePriv = rrGetScrPriv(slave);
> -            for (i = 0; i < pSlavePriv->numCrtcs; i++)
> +            for (i = 0; i < pSlavePriv->numCrtcs; i++) {
> +                if (has_primary &&
> +                    primary_crtc == pSlavePriv->crtcs[i]) {
> +                    has_primary = 0;
> +                    continue;
> +                }
>                   RRXineramaWriteCrtc(client, pSlavePriv->crtcs[i]);
> +            }
>           }
>       }
>
>

Aside from the above,
Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

-- 
Aaron


More information about the xorg-devel mailing list