On 28 January 2015 at 08:40, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > This is ported from the same code in the ati and intel drivers, > > It uses the same option name as nvidia and the other DDXes to > disable tearing down outputs as it is hard to avoid racing with clients. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > ---
I wrote a similar patch, http://lists.x.org/archives/xorg-devel/2014-December/044754.html though not using an option. Keith wrote that we can't merge it without testing, i.e. possible on none-MST maschines with: http://lists.x.org/archives/xorg-devel/2014-December/044755.html But, as nobody tested it I was lurking around for 1.17 to send a merge request afterwards. > hw/xfree86/drivers/modesetting/driver.c | 6 + > hw/xfree86/drivers/modesetting/drmmode_display.c | 212 > +++++++++++++++++++++-- > hw/xfree86/drivers/modesetting/drmmode_display.h | 1 + > 3 files changed, 206 insertions(+), 13 deletions(-) > > diff --git a/hw/xfree86/drivers/modesetting/driver.c > b/hw/xfree86/drivers/modesetting/driver.c > index d52517d..aaf40c9 100644 > --- a/hw/xfree86/drivers/modesetting/driver.c > +++ b/hw/xfree86/drivers/modesetting/driver.c > @@ -123,6 +123,7 @@ typedef enum { > OPTION_DEVICE_PATH, > OPTION_SHADOW_FB, > OPTION_ACCEL_METHOD, > + OPTION_DELETE_DP_12_DISP, > } modesettingOpts; > > static const OptionInfoRec Options[] = { > @@ -130,6 +131,7 @@ static const OptionInfoRec Options[] = { > {OPTION_DEVICE_PATH, "kmsdev", OPTV_STRING, {0}, FALSE}, > {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, > {OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE}, > + {OPTION_DELETE_DP_12_DISP, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, > {0}, FALSE}, > {-1, NULL, OPTV_NONE, {0}, FALSE} > }; > > @@ -768,6 +770,10 @@ PreInit(ScrnInfoPtr pScrn, int flags) > ms->drmmode.sw_cursor = TRUE; > } > > + if (xf86ReturnOptValBool(ms->Options, OPTION_DELETE_DP_12_DISP, FALSE)) { > + ms->drmmode.delete_dp_12_displays = TRUE; > + } > + > ms->cursor_width = 64; > ms->cursor_height = 64; > ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value); > diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c > b/hw/xfree86/drivers/modesetting/drmmode_display.c > index 8dc6b32..ee2fc2f 100644 > --- a/hw/xfree86/drivers/modesetting/drmmode_display.c > +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c > @@ -326,6 +326,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr > mode, > continue; > > drmmode_output = output->driver_private; > + if (drmmode_output->output_id == -1) > + continue; > output_ids[output_count] = > drmmode_output->mode_output->connector_id; > output_count++; > @@ -366,10 +368,14 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr > mode, > /* go through all the outputs and force DPMS them back on? */ > for (i = 0; i < xf86_config->num_output; i++) { > xf86OutputPtr output = xf86_config->output[i]; > + drmmode_output_private_ptr drmmode_output; > > if (output->crtc != crtc) > continue; > > + drmmode_output = output->driver_private; > + if (drmmode_output->output_id == -1) > + continue; > output->funcs->dpms(output, DPMSModeOn); > } > } > @@ -712,6 +718,9 @@ drmmode_output_detect(xf86OutputPtr output) > drmmode_ptr drmmode = drmmode_output->drmmode; > xf86OutputStatus status; > > + if (drmmode_output->output_id == -1) > + return XF86OutputStatusDisconnected; > + > drmModeFreeConnector(drmmode_output->mode_output); > > drmmode_output->mode_output = > @@ -1111,22 +1120,134 @@ static const char *const output_names[] = { > "DSI", > }; > > +static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id) > +{ > + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); > + int i; > + for (i = 0; i < xf86_config->num_output; i++) { > + xf86OutputPtr output = xf86_config->output[i]; > + drmmode_output_private_ptr drmmode_output; > + > + drmmode_output = output->driver_private; > + if (drmmode_output->output_id == id) > + return output; > + } > + return NULL; > +} > + > +static int parse_path_blob(drmModePropertyBlobPtr path_blob, int > *conn_base_id, char **path) > +{ > + char *conn; > + char conn_id[5]; > + int id, len; > + char *blob_data; > + > + if (!path_blob) > + return -1; > + > + blob_data = path_blob->data; > + /* we only handle MST paths for now */ > + if (strncmp(blob_data, "mst:", 4)) > + return -1; > + > + conn = strchr(blob_data + 4, '-'); > + if (!conn) > + return -1; > + len = conn - (blob_data + 4); > + if (len + 1> 5) > + return -1; > + memcpy(conn_id, blob_data + 4, len); > + conn_id[len + 1] = '\0'; > + id = strtoul(conn_id, NULL, 10); > + > + *conn_base_id = id; > + > + *path = conn + 1; > + return 0; > +} > + > static void > -drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr > mode_res, int num) > +drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char > *name, > + drmModePropertyBlobPtr path_blob) > { > + int ret; > + char *extra_path; > + int conn_id; > xf86OutputPtr output; > + > + ret = parse_path_blob(path_blob, &conn_id, &extra_path); > + if (ret == -1) > + goto fallback; > + > + output = find_output(pScrn, conn_id); > + if (!output) > + goto fallback; > + > + snprintf(name, 32, "%s-%s", output->name, extra_path); > + ErrorF("setting name to %s\n", name); > + return; > + > + fallback: > + if (koutput->connector_type >= MS_ARRAY_SIZE(output_names)) > + snprintf(name, 32, "Unknown-%d", koutput->connector_type_id - 1); > +#ifdef MODESETTING_OUTPUT_SLAVE_SUPPORT > + else if (pScrn->is_gpu) > + snprintf(name, 32, "%s-%d-%d", > output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + > 1, koutput->connector_type_id - 1); > +#endif > + else > + snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], > koutput->connector_type_id - 1); > +} > +static void > +drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr > mode_res, int num, Bool dynamic) > +{ > + xf86OutputPtr output; > + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); > drmModeConnectorPtr koutput; > drmModeEncoderPtr *kencoders = NULL; > drmmode_output_private_ptr drmmode_output; > drmModePropertyPtr props; > char name[32]; > int i; > + drmModePropertyBlobPtr path_blob = NULL; > > koutput = > drmModeGetConnector(drmmode->fd, mode_res->connectors[num]); > if (!koutput) > return; > > + for (i = 0; i < koutput->count_props; i++) { > + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); > + if (props && (props->flags & DRM_MODE_PROP_BLOB)) { > + if (!strcmp(props->name, "PATH")) { > + path_blob = drmModeGetPropertyBlob(drmmode->fd, > koutput->prop_values[i]); > + drmModeFreeProperty(props); > + break; > + } > + drmModeFreeProperty(props); > + } > + } > + > + drmmode_create_name(pScrn, koutput, name, path_blob); > + > + if (path_blob) > + drmModeFreePropertyBlob(path_blob); > + > + if (path_blob && dynamic) { > + /* see if we have an output with this name already > + and hook stuff up */ > + for (i = 0; i < xf86_config->num_output; i++) { > + output = xf86_config->output[i]; > + > + if (strncmp(output->name, name, 32)) > + continue; > + > + drmmode_output = output->driver_private; > + drmmode_output->output_id = mode_res->connectors[num]; > + drmmode_output->mode_output = koutput; > + return; > + } > + } > + > kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); > if (!kencoders) { > goto out_free_encoders; > @@ -1139,17 +1260,6 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr > drmmode, drmModeResPtr mode_r > } > } > > - /* need to do smart conversion here for compat with non-kms ATI driver */ > - if (koutput->connector_type >= MS_ARRAY_SIZE(output_names)) > - snprintf(name, 32, "Unknown-%d", koutput->connector_type_id - 1); > - else if (pScrn->is_gpu) > - snprintf(name, 32, "%s-%d-%d", output_names[koutput->connector_type], > - pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1, > - koutput->connector_type_id - 1); > - else > - snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], > - koutput->connector_type_id - 1); > - > output = xf86OutputCreate(pScrn, &drmmode_output_funcs, name); > if (!output) { > goto out_free_encoders; > @@ -1192,6 +1302,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr > drmmode, drmModeResPtr mode_r > } > } > > + if (dynamic) > + output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), > output->name, strlen(output->name), output); > return; > out_free_encoders: > if (kencoders) { > @@ -1451,7 +1563,7 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr > drmmode, int cpp) > drmmode_crtc_init(pScrn, drmmode, mode_res, i); > > for (i = 0; i < mode_res->count_connectors; i++) > - drmmode_output_init(pScrn, drmmode, mode_res, i); > + drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE); > > /* workout clones */ > drmmode_clones_init(pScrn, drmmode, mode_res); > @@ -1620,11 +1732,85 @@ drmmode_handle_uevents(int fd, void *closure) > drmmode_ptr drmmode = closure; > ScrnInfoPtr scrn = drmmode->scrn; > struct udev_device *dev; > + drmModeResPtr mode_res; > + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); > + int i, j; > + Bool found; > + Bool changed = FALSE; > > dev = udev_monitor_receive_device(drmmode->uevent_monitor); > if (!dev) > return; > > + mode_res = drmModeGetResources(drmmode->fd); > + if (!mode_res) > + goto out; > + > + if (mode_res->count_crtcs != config->num_crtc) { > + ErrorF("number of CRTCs changed - failed to handle, %d vs %d\n", > mode_res->count_crtcs, config->num_crtc); > + goto out_free_res; > + } > + > + /* figure out if we have gotten rid of any connectors > + traverse old output list looking for outputs */ > +restart_destroy: > + for (i = 0; i < config->num_output; i++) { > + xf86OutputPtr output = config->output[i]; > + drmmode_output_private_ptr drmmode_output; > + > + drmmode_output = output->driver_private; > + found = FALSE; > + for (j = 0; j < mode_res->count_connectors; j++) { > + if (mode_res->connectors[j] == drmmode_output->output_id) { > + found = TRUE; > + break; > + } > + } > + if (found) > + continue; > + > + drmModeFreeConnector(drmmode_output->mode_output); > + drmmode_output->mode_output = NULL; > + drmmode_output->output_id = -1; > + > + changed = TRUE; > + if (drmmode->delete_dp_12_displays) { > + RROutputDestroy(output->randr_output); In my patch I had to remove the output from crtcs using it. Otherwise the server died in a horrible fire. You don't need this? Looks like I have to study your patch and compare what I did wrong. > + xf86OutputDestroy(output); > + goto restart_destroy; > + } > + } > + > + /* find new output ids we don't have outputs for */ > + for (i = 0; i < mode_res->count_connectors; i++) { > + found = FALSE; > + > + for (j = 0; j < config->num_output; j++) { > + xf86OutputPtr output = config->output[j]; > + drmmode_output_private_ptr drmmode_output; > + > + drmmode_output = output->driver_private; > + if (mode_res->connectors[i] == drmmode_output->output_id) { > + found = TRUE; > + break; > + } > + } > + if (found) > + continue; > + > + changed = TRUE; > + drmmode_output_init(scrn, drmmode, mode_res, i, 1); > + > + } > + > + if (changed) { > + RRSetChanged(xf86ScrnToScreen(scrn)); > + RRTellChanged(xf86ScrnToScreen(scrn)); > + } > + > +out_free_res: > + drmModeFreeResources(mode_res); > +out: > RRGetInfo(xf86ScrnToScreen(scrn), TRUE); > udev_device_unref(dev); > } > diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h > b/hw/xfree86/drivers/modesetting/drmmode_display.h > index f4989b8..769842d 100644 > --- a/hw/xfree86/drivers/modesetting/drmmode_display.h > +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h > @@ -79,6 +79,7 @@ typedef struct { > uint32_t triple_buffer_name; > > DevPrivateKeyRec pixmapPrivateKeyRec; > + Bool delete_dp_12_displays; > } drmmode_rec, *drmmode_ptr; > > typedef struct { > -- > 2.1.0 > > _______________________________________________ > xorg-devel@lists.x.org: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: http://lists.x.org/mailman/listinfo/xorg-devel _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel