On Fri, Nov 28, 2014 at 11:20:53AM +0100, Daniel Martin wrote: > From: Daniel Martin <[email protected]> > > When receiving a hotplug uevent, check if we have to add or remove > outputs and act accordingly. > > Signed-off-by: Daniel Martin <[email protected]> > --- > With this patch we create or destroy outputs as a reaction to uevents. > > Due to my limited experience, the solution is either total crap, cause > I'm doing it wrong, or it is that complicated, cause the server never > had disappearing outputs in mind, or a combination of both. > > hw/xfree86/drivers/modesetting/drmmode_display.c | 150 > ++++++++++++++++++++++- > 1 file changed, 148 insertions(+), 2 deletions(-) > > diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c > b/hw/xfree86/drivers/modesetting/drmmode_display.c > index 474e5b6..876af68 100644 > --- a/hw/xfree86/drivers/modesetting/drmmode_display.c > +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c > @@ -43,6 +43,7 @@ > #include "xf86Crtc.h" > #include "drmmode_display.h" > > +#include <xf86RandR12.h> > #include <cursorstr.h> > > #include <X11/extensions/dpmsconst.h> > @@ -785,8 +786,10 @@ drmmode_output_destroy(xf86OutputPtr output) > free(drmmode_output->props[i].atoms); > } > free(drmmode_output->props); > - for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { > - drmModeFreeEncoder(drmmode_output->mode_encoders[i]); > + if (drmmode_output->mode_output) { > + for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) { > + drmModeFreeEncoder(drmmode_output->mode_encoders[i]); > + }
I'll split this hunk off into a distinct patch and attach the trace to
express why it is necessary.
> }
> free(drmmode_output->mode_encoders);
> drmModeFreeConnector(drmmode_output->mode_output);
> @@ -1488,12 +1491,155 @@ drmmode_setup_colormap(ScreenPtr pScreen,
> ScrnInfoPtr pScrn)
> }
>
> #ifdef CONFIG_UDEV_KMS
> +static Bool
> +drmmode_output_add(drmmode_ptr drmmode, int nth_connector)
> +{
> + ScrnInfoPtr scrn = drmmode->scrn;
> + xf86OutputPtr output = drmmode_output_init(scrn, drmmode, nth_connector);
> +
> + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Adding output %s\n", output->name);
Possible NULL dereference, move this below the following check.
> + if (!output)
> + return FALSE;
> +
> + output->randr_output = RROutputCreate(scrn->pScreen, output->name,
> + strlen(output->name), output);
> + if (!output->randr_output) {
> + xf86OutputDestroy(output);
> + return FALSE;
> + }
> +
> + drmmode_output_create_resources(output);
> + RRPostPendingProperties(output->randr_output);
> +
> + return TRUE;
> +}
> +
> +static Bool
> +drmmode_output_del(xf86OutputPtr output)
> +{
> + ScrnInfoPtr scrn = output->scrn;
> + rrScrPrivPtr pScrPriv = rrGetScrPriv(scrn->pScreen);
> + int i, j;
> +
> + output->funcs->dpms(output, DPMSModeOff);
> +
> + /* Remove the RROutput from RRCrtc, if any. */
> + if (output->randr_output->crtc) {
> + RRCrtcPtr rr_crtc = output->randr_output->crtc;
> +
> + if (rr_crtc->numOutputs < 2) {
> + RRCrtcSet(rr_crtc, NULL, 0, 0, 0, 0, NULL);
> + } else {
> + RROutputPtr *rr_outputs = calloc(rr_crtc->numOutputs,
> + sizeof(RROutputPtr));
> + if (!rr_outputs)
> + return FALSE;
> +
> + for (i = 0, j = 0; i < rr_crtc->numOutputs; i++) {
> + if (rr_crtc->outputs[i] != output->randr_output) {
> + rr_outputs[j] = rr_crtc->outputs[i];
> + }
> + j++;
> + }
> +
> + RRCrtcSet(rr_crtc, rr_crtc->mode, rr_crtc->x, rr_crtc->y,
> + rr_crtc->rotation, rr_crtc->numOutputs - 1,
> rr_outputs);
> + free(rr_outputs);
> + }
> + }
> +
> + /* Remove the RROutput from the list of available outputs. */
> + for (i = 0; i < pScrPriv->numOutputs; i++) {
> + if (pScrPriv->outputs[i] == output->randr_output) {
> + memmove(&pScrPriv->outputs[i], &pScrPriv->outputs[i + 1],
> + ((pScrPriv->numOutputs - (i + 1)) *
> sizeof(RROutputPtr)));
> + pScrPriv->numOutputs--;
> + break;
> + }
> + }
> +
> + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Removing output %s\n",
> output->name);
> +
> + RROutputDestroy(output->randr_output);
> + output->randr_output = NULL;
> +
> + xf86OutputDestroy(output);
> +
> + return TRUE;
> +}
> +
> void
> drmmode_output_eval(drmmode_ptr drmmode)
> {
> ScrnInfoPtr scrn = drmmode->scrn;
> + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
> +
> + drmModeResPtr mode_res = NULL;
> +
> + int old_num_output = xf86_config->num_output;
> + xf86OutputPtr *output_del_list = NULL;
> +
> + Bool changed = FALSE;
> + int i, j;
> +
> + mode_res = drmModeGetResources(drmmode->fd);
> + if (mode_res) {
> + drmModeFreeResources(drmmode->mode_res);
> + drmmode->mode_res = mode_res;
> + } else
> + return;
> +
> + output_del_list = calloc(xf86_config->num_output + 1,
> + sizeof(*output_del_list));
> + if (!output_del_list)
> + goto out;
> +
> + /* Track all currently known outputs in output_del_list. We'll NULL each
> + * entry which we can match with one connector in mode_res->connectors.
> + * Later, every entry not being NULL is an output we have to delete. */
> + memcpy(output_del_list, xf86_config->output,
> + xf86_config->num_output * sizeof(*output_del_list));
> +
> + /* Check for outputs we already know or have to add. */
> + for (i = 0; i < mode_res->count_connectors; i++) {
> + Bool found = FALSE;
> +
> + for (j = 0; j < old_num_output; j++) {
> + drmmode_output_private_ptr drmmode_output;
> +
> + if (output_del_list[j] == NULL)
> + continue;
> +
> + drmmode_output = output_del_list[j]->driver_private;
> + if (drmmode_output->output_id == mode_res->connectors[i]) {
> + found = TRUE;
> + break;
> + }
> + }
> +
> + if (found)
> + /* Found the output, NULL the entry. */
> + output_del_list[j] = NULL;
> + else
> + changed |= drmmode_output_add(drmmode, i);
> + }
> +
> + for (i = 0; i < old_num_output; i++)
> + if (output_del_list[i] != NULL)
> + changed |= drmmode_output_del(output_del_list[i]);
> +
> + if (changed) {
> + xf86DisableUnusedFunctions(scrn);
> + drmmode_clones_init(scrn, drmmode);
> +
> + xf86RandR12TellChanged(xf86ScrnToScreen(scrn));
> + }
>
> RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
> +
> +out:
> + free(output_del_list);
> }
>
> static void
> --
> 2.1.3
>
pgpFwiHQKDsj5.pgp
Description: PGP signature
_______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
