diff options
-rw-r--r-- | hw/xfree86/common/xf86Config.c | 60 | ||||
-rw-r--r-- | hw/xfree86/common/xf86Helper.c | 13 | ||||
-rw-r--r-- | hw/xfree86/common/xf86str.h | 10 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/drmmode_display.c | 287 | ||||
-rw-r--r-- | hw/xfree86/drivers/modesetting/drmmode_display.h | 2 | ||||
-rw-r--r-- | hw/xfree86/man/xorg.conf.man | 13 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86Crtc.c | 137 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86RandR12.c | 66 | ||||
-rw-r--r-- | hw/xfree86/parser/Configint.h | 2 | ||||
-rw-r--r-- | hw/xfree86/parser/Screen.c | 22 | ||||
-rw-r--r-- | hw/xfree86/parser/xf86Parser.h | 5 | ||||
-rw-r--r-- | hw/xfree86/parser/xf86tokens.h | 1 | ||||
-rw-r--r-- | randr/randrstr.h | 9 | ||||
-rw-r--r-- | randr/rrmonitor.c | 6 |
14 files changed, 577 insertions, 56 deletions
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 7edac0b16..b8ec8a0ef 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -126,7 +126,7 @@ static Bool configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, MessageType from); static Bool configMonitor(MonPtr monitorp, XF86ConfMonitorPtr conf_monitor); static Bool configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, - Bool active); + Bool active, Bool gpu); static Bool configInput(InputInfoPtr pInfo, XF86ConfInputPtr conf_input, MessageType from); static Bool configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display); @@ -390,7 +390,7 @@ const char ** xf86DriverlistFromConfig(void) { int count = 0; - int j; + int j, k; const char **modulearray; screenLayoutPtr slp; @@ -411,8 +411,10 @@ xf86DriverlistFromConfig(void) */ if (xf86ConfigLayout.screens) { slp = xf86ConfigLayout.screens; - while ((slp++)->screen) { + while (slp->screen) { count++; + count += slp->screen->num_gpu_devices; + slp++; } } @@ -435,6 +437,10 @@ xf86DriverlistFromConfig(void) while (slp->screen) { modulearray[count] = slp->screen->device->driver; count++; + for (k = 0; k < slp->screen->num_gpu_devices; k++) { + modulearray[count] = slp->screen->gpu_devices[k]->driver; + count++; + } slp++; } @@ -1631,7 +1637,7 @@ configLayout(serverLayoutPtr servlayoutp, XF86ConfLayoutPtr conf_layout, idp = conf_layout->lay_inactive_lst; count = 0; while (idp) { - if (!configDevice(&gdp[count], idp->inactive_device, FALSE)) + if (!configDevice(&gdp[count], idp->inactive_device, FALSE, FALSE)) goto bail; count++; idp = (XF86ConfInactivePtr) idp->list.next; @@ -1769,6 +1775,7 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, XF86ConfAdaptorLinkPtr conf_adaptor; Bool defaultMonitor = FALSE; XF86ConfScreenRec local_conf_screen; + int i; if (!conf_screen) { memset(&local_conf_screen, 0, sizeof(local_conf_screen)); @@ -1811,12 +1818,41 @@ configScreen(confScreenPtr screenp, XF86ConfScreenPtr conf_screen, int scrnum, xf86Msg(X_DEFAULT, "No device specified for screen \"%s\".\n" "\tUsing the first device section listed.\n", screenp->id); } - if (configDevice(screenp->device, conf_screen->scrn_device, TRUE)) { + if (configDevice(screenp->device, conf_screen->scrn_device, TRUE, FALSE)) { screenp->device->myScreenSection = screenp; } else { screenp->device = NULL; } + + if (conf_screen->num_gpu_devices == 0 && xf86configptr->conf_device_lst) { + XF86ConfDevicePtr sdevice = xf86configptr->conf_device_lst->list.next; + + for (i = 0; i < MAX_GPUDEVICES; i++) { + if (!sdevice) + break; + + FIND_SUITABLE (XF86ConfDevicePtr, sdevice, conf_screen->scrn_gpu_devices[i]); + if (!conf_screen->scrn_gpu_devices[i]) + break; + screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec)); + if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) { + screenp->gpu_devices[i]->myScreenSection = screenp; + } + sdevice = conf_screen->scrn_gpu_devices[i]->list.next; + } + screenp->num_gpu_devices = i; + + } else { + for (i = 0; i < conf_screen->num_gpu_devices; i++) { + screenp->gpu_devices[i] = xnfcalloc(1, sizeof(GDevRec)); + if (configDevice(screenp->gpu_devices[i], conf_screen->scrn_gpu_devices[i], TRUE, TRUE)) { + screenp->gpu_devices[i]->myScreenSection = screenp; + } + } + screenp->num_gpu_devices = conf_screen->num_gpu_devices; + } + screenp->options = conf_screen->scrn_option_lst; /* @@ -2110,7 +2146,7 @@ configDisplay(DispPtr displayp, XF86ConfDisplayPtr conf_display) } static Bool -configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) +configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active, Bool gpu) { int i; @@ -2118,10 +2154,14 @@ configDevice(GDevPtr devicep, XF86ConfDevicePtr conf_device, Bool active) return FALSE; } - if (active) - xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", - conf_device->dev_identifier); - else + if (active) { + if (gpu) + xf86Msg(X_CONFIG, "| |-->GPUDevice \"%s\"\n", + conf_device->dev_identifier); + else + xf86Msg(X_CONFIG, "| |-->Device \"%s\"\n", + conf_device->dev_identifier); + } else xf86Msg(X_CONFIG, "|-->Inactive Device \"%s\"\n", conf_device->dev_identifier); diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c index 6a3525052..359bac762 100644 --- a/hw/xfree86/common/xf86Helper.c +++ b/hw/xfree86/common/xf86Helper.c @@ -1369,7 +1369,7 @@ xf86MatchDevice(const char *drivername, GDevPtr ** sectlist) { GDevPtr gdp, *pgdp = NULL; confScreenPtr screensecptr; - int i, j; + int i, j, k; if (sectlist) *sectlist = NULL; @@ -1413,6 +1413,17 @@ xf86MatchDevice(const char *drivername, GDevPtr ** sectlist) pgdp = xnfreallocarray(pgdp, i + 2, sizeof(GDevPtr)); pgdp[i++] = screensecptr->device; } + for (k = 0; k < screensecptr->num_gpu_devices; k++) { + if ((screensecptr->gpu_devices[k]->driver != NULL) + && (xf86NameCmp(screensecptr->gpu_devices[k]->driver, drivername) == 0) + && (!screensecptr->gpu_devices[k]->claimed)) { + /* + * we have a matching driver that wasn't claimed, yet + */ + pgdp = xnfrealloc(pgdp, (i + 2) * sizeof(GDevPtr)); + pgdp[i++] = screensecptr->gpu_devices[k]; + } + } } /* Then handle the inactive devices */ diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h index 643a65db1..a58fafebd 100644 --- a/hw/xfree86/common/xf86str.h +++ b/hw/xfree86/common/xf86str.h @@ -440,6 +440,7 @@ typedef struct _confxvadaptrec { void *options; } confXvAdaptorRec, *confXvAdaptorPtr; +#define MAX_GPUDEVICES 4 typedef struct _confscreenrec { const char *id; int screennum; @@ -453,6 +454,9 @@ typedef struct _confscreenrec { int numxvadaptors; confXvAdaptorPtr xvadaptors; void *options; + + int num_gpu_devices; + GDevPtr gpu_devices[MAX_GPUDEVICES]; } confScreenRec, *confScreenPtr; typedef enum { @@ -512,6 +516,9 @@ typedef struct _confdrirec { #define NUM_RESERVED_POINTERS 14 #define NUM_RESERVED_FUNCS 10 +/* let clients know they can use this */ +#define XF86_SCRN_HAS_PREFER_CLONE 1 + typedef void *(*funcPointer) (void); /* flags for depth 24 pixmap options */ @@ -768,6 +775,9 @@ typedef struct _ScrnInfoRec { ClockRangePtr clockRanges; int adjustFlags; + /* initial rightof support disable */ + int preferClone; + /* * These can be used when the minor ABI version is incremented. * The NUM_* parameters must be reduced appropriately to keep the diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c index a8de5f9e7..f3c9909ef 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); } } @@ -687,7 +693,7 @@ drmmode_crtc_vblank_pipe(int crtc_id) } static void -drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) +drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num) { xf86CrtcPtr crtc; drmmode_crtc_private_ptr drmmode_crtc; @@ -698,7 +704,7 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); drmmode_crtc->mode_crtc = - drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); + drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]); drmmode_crtc->drmmode = drmmode; drmmode_crtc->vblank_pipe = drmmode_crtc_vblank_pipe(num); crtc->driver_private = drmmode_crtc; @@ -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 = @@ -740,6 +749,46 @@ drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) return MODE_OK; } +static void +drmmode_output_attach_tile(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + struct xf86CrtcTileInfo tile_info, *set = NULL; + + if (!koutput) { + xf86OutputSetTile(output, NULL); + return; + } + + /* look for a TILE property */ + for (i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr props; + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (!props) + continue; + + if (!(props->flags & DRM_MODE_PROP_BLOB)) { + drmModeFreeProperty(props); + continue; + } + + if (!strcmp(props->name, "TILE")) { + drmModeFreePropertyBlob(drmmode_output->tile_blob); + drmmode_output->tile_blob = + drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + if (drmmode_output->tile_blob) { + if (xf86OutputParseKMSTile(drmmode_output->tile_blob->data, drmmode_output->tile_blob->length, &tile_info) == TRUE) + set = &tile_info; + } + xf86OutputSetTile(output, set); +} + static Bool has_panel_fitter(xf86OutputPtr output) { @@ -848,6 +897,8 @@ drmmode_output_get_modes(xf86OutputPtr output) } xf86OutputSetEDID(output, mon); + drmmode_output_attach_tile(output); + /* modes should already be available */ for (i = 0; i < koutput->count_modes; i++) { Mode = xnfalloc(sizeof(DisplayModeRec)); @@ -873,11 +924,13 @@ 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]); + } + drmModeFreeConnector(drmmode_output->mode_output); } free(drmmode_output->mode_encoders); - drmModeFreeConnector(drmmode_output->mode_output); free(drmmode_output); output->driver_private = NULL; } @@ -1111,22 +1164,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_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); + 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, int num) +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, drmmode->mode_res->connectors[num]); + 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 +1304,6 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) } } - /* 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; @@ -1161,7 +1315,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) goto out_free_encoders; } - drmmode_output->output_id = drmmode->mode_res->connectors[num]; + drmmode_output->output_id = mode_res->connectors[num]; drmmode_output->mode_output = koutput; drmmode_output->mode_encoders = kencoders; drmmode_output->drmmode = drmmode; @@ -1192,6 +1346,8 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) } } + if (dynamic) + output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output); return; out_free_encoders: if (kencoders) { @@ -1231,7 +1387,7 @@ find_clones(ScrnInfoPtr scrn, xf86OutputPtr output) } static void -drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) +drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res) { int i, j; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -1246,8 +1402,8 @@ drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode) for (j = 0; j < drmmode_output->mode_output->count_encoders; j++) { int k; - for (k = 0; k < drmmode->mode_res->count_encoders; k++) { - if (drmmode->mode_res->encoders[k] == + for (k = 0; k < mode_res->count_encoders; k++) { + if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id) drmmode_output->enc_mask |= (1 << k); } @@ -1425,6 +1581,7 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) int i; int ret; uint64_t value = 0; + drmModeResPtr mode_res; /* check for dumb capability */ ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value); @@ -1438,23 +1595,24 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) drmmode->scrn = pScrn; drmmode->cpp = cpp; - drmmode->mode_res = drmModeGetResources(drmmode->fd); - if (!drmmode->mode_res) + mode_res = drmModeGetResources(drmmode->fd); + if (!mode_res) return FALSE; - xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, - drmmode->mode_res->max_height); - for (i = 0; i < drmmode->mode_res->count_crtcs; i++) + xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, + mode_res->max_height); + for (i = 0; i < mode_res->count_crtcs; i++) if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i) - drmmode_crtc_init(pScrn, drmmode, i); + drmmode_crtc_init(pScrn, drmmode, mode_res, i); - for (i = 0; i < drmmode->mode_res->count_connectors; i++) - drmmode_output_init(pScrn, drmmode, i); + for (i = 0; i < mode_res->count_connectors; i++) + drmmode_output_init(pScrn, drmmode, mode_res, i, FALSE); /* workout clones */ - drmmode_clones_init(pScrn, drmmode); + drmmode_clones_init(pScrn, drmmode, mode_res); + drmModeFreeResources(mode_res); #if XF86_CRTC_VERSION >= 5 xf86ProviderSetup(pScrn, NULL, "modesetting"); #endif @@ -1618,11 +1776,78 @@ 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 */ + 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; + } + + /* 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 3a8959ac3..b0e45b6e0 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -47,7 +47,6 @@ typedef struct { int fd; unsigned fb_id; unsigned old_fb_id; - drmModeResPtr mode_res; drmModeFBPtr mode_fb; int cpp; ScrnInfoPtr scrn; @@ -121,6 +120,7 @@ typedef struct { drmModeConnectorPtr mode_output; drmModeEncoderPtr *mode_encoders; drmModePropertyBlobPtr edid_blob; + drmModePropertyBlobPtr tile_blob; int dpms_enum_id; int num_props; drmmode_prop_ptr props; diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man index d26c3cc4d..e9b6d9990 100644 --- a/hw/xfree86/man/xorg.conf.man +++ b/hw/xfree86/man/xorg.conf.man @@ -1906,6 +1906,7 @@ sections have the following format: .B "Section \*qScreen\*q" .BI " Identifier \*q" name \*q .BI " Device \*q" devid \*q +.BI " GPUDevice \*q" devid \*q .BI " Monitor \*q" monid \*q .I " entries" .I " ..." @@ -1949,6 +1950,18 @@ of a .B Device section in the config file. .TP 7 +.BI "GPUDevice \*q" device\-id \*q +This entry specifies the +.B Device +section to be used as a secondary GPU device for this screen. When multiple graphics cards are +present, this is what ties a specific secondary card to a screen. The +.I device\-id +must match the +.B Identifier +of a +.B Device +section in the config file. This can be specified up to 4 times for a single screen. +.TP 7 .BI "Monitor \*q" monitor\-id \*q specifies which monitor description is to be used for this screen. If a diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 127e5431b..38bc58cbc 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -1124,6 +1124,15 @@ xf86InitialOutputPositions(ScrnInfoPtr scrn, DisplayModePtr * modes) int o; int min_x, min_y; + /* check for initial right-of heuristic */ + for (o = 0; o < config->num_output; o++) + { + xf86OutputPtr output = config->output[o]; + + if (output->initial_x || output->initial_y) + return TRUE; + } + for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -2103,6 +2112,118 @@ bestModeForAspect(xf86CrtcConfigPtr config, Bool *enabled, float aspect) return match; } +static int +numEnabledOutputs(xf86CrtcConfigPtr config, Bool *enabled) +{ + int i = 0, p; + + for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++) ; + + return i; +} + +static Bool +xf86TargetRightOf(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, + DisplayModePtr *modes, Bool *enabled, + int width, int height) +{ + int o; + int w = 0; + Bool has_tile = FALSE; + uint32_t configured_outputs; + + if (scrn->preferClone) + return FALSE; + + if (numEnabledOutputs(config, enabled) < 2) + return FALSE; + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + DisplayModePtr mode = + xf86OutputHasPreferredMode(config->output[o], width, height); + + if (!mode) + return FALSE; + + w += mode->HDisplay; + } + + if (w > width) + return FALSE; + + w = 0; + configured_outputs = 0; + + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + DisplayModePtr mode = + xf86OutputHasPreferredMode(config->output[o], width, height); + + if (configured_outputs & (1 << o)) + continue; + + if (config->output[o]->tile_info.group_id) { + has_tile = TRUE; + continue; + } + + config->output[o]->initial_x = w; + w += mode->HDisplay; + + configured_outputs |= (1 << o); + modes[o] = mode; + } + + if (has_tile) { + for (o = -1; nextEnabledOutput(config, enabled, &o); ) { + int ht, vt, ot; + int add_x, cur_x = w; + struct xf86CrtcTileInfo *tile_info = &config->output[o]->tile_info, *this_tile; + if (configured_outputs & (1 << o)) + continue; + if (!tile_info->group_id) + continue; + + if (tile_info->tile_h_loc != 0 && tile_info->tile_v_loc != 0) + continue; + + for (ht = 0; ht < tile_info->num_h_tile; ht++) { + int cur_y = 0; + add_x = 0; + for (vt = 0; vt < tile_info->num_v_tile; vt++) { + + for (ot = -1; nextEnabledOutput(config, enabled, &ot); ) { + + DisplayModePtr mode = + xf86OutputHasPreferredMode(config->output[ot], width, height); + if (!config->output[ot]->tile_info.group_id) + continue; + + this_tile = &config->output[ot]->tile_info; + if (this_tile->group_id != tile_info->group_id) + continue; + + if (this_tile->tile_h_loc != ht || + this_tile->tile_v_loc != vt) + continue; + + config->output[ot]->initial_x = cur_x; + config->output[ot]->initial_y = cur_y; + + if (vt == 0) + add_x = this_tile->tile_h_size; + cur_y += this_tile->tile_v_size; + configured_outputs |= (1 << ot); + modes[ot] = mode; + } + } + cur_x += add_x; + } + w = cur_x; + } + } + return TRUE; +} + static Bool xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, DisplayModePtr * modes, Bool *enabled, @@ -2179,14 +2300,10 @@ xf86TargetPreferred(ScrnInfoPtr scrn, xf86CrtcConfigPtr config, */ if (!ret) do { - int i = 0; float aspect = 0.0; DisplayModePtr a = NULL, b = NULL; - /* count the number of enabled outputs */ - for (i = 0, p = -1; nextEnabledOutput(config, enabled, &p); i++); - - if (i != 1) + if (numEnabledOutputs(config, enabled) != 1) break; p = -1; @@ -2492,6 +2609,8 @@ xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow) else { if (xf86TargetUserpref(scrn, config, modes, enabled, width, height)) xf86DrvMsg(i, X_INFO, "Using user preference for initial modes\n"); + else if (xf86TargetRightOf(scrn, config, modes, enabled, width, height)) + xf86DrvMsg(i, X_INFO, "Using spanning desktop for initial modes\n"); else if (xf86TargetPreferred (scrn, config, modes, enabled, width, height)) xf86DrvMsg(i, X_INFO, "Using exact sizes for initial modes\n"); @@ -2511,9 +2630,11 @@ xf86InitialConfiguration(ScrnInfoPtr scrn, Bool canGrow) "Output %s enabled but has no modes\n", config->output[o]->name); else - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Output %s using initial mode %s\n", - config->output[o]->name, modes[o]->name); + xf86DrvMsg (scrn->scrnIndex, X_INFO, + "Output %s using initial mode %s +%d+%d\n", + config->output[o]->name, modes[o]->name, + config->output[o]->initial_x, + config->output[o]->initial_y); } /* diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index fb7312814..0d446da64 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -1562,6 +1562,70 @@ xf86RandR12CreateObjects12(ScreenPtr pScreen) return TRUE; } +static void +xf86RandR12CreateMonitors(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, ot; + int ht, vt; + int ret; + char buf[25]; + + for (o = 0; o < config->num_output; o++) { + xf86OutputPtr output = config->output[o]; + struct xf86CrtcTileInfo *tile_info = &output->tile_info, *this_tile; + RRMonitorPtr monitor; + int output_num, num_outputs; + if (!tile_info->group_id) + continue; + + if (tile_info->tile_h_loc || + tile_info->tile_v_loc) + continue; + + num_outputs = tile_info->num_h_tile * tile_info->num_v_tile; + + monitor = RRMonitorAlloc(num_outputs); + if (!monitor) + return; + monitor->pScreen = pScreen; + snprintf(buf, 25, "Auto-Monitor-%d", tile_info->group_id); + monitor->name = MakeAtom(buf, strlen(buf), TRUE); + monitor->primary = 0; + monitor->automatic = TRUE; + memset(&monitor->geometry.box, 0, sizeof(monitor->geometry.box)); + + output_num = 0; + for (ht = 0; ht < tile_info->num_h_tile; ht++) { + for (vt = 0; vt < tile_info->num_v_tile; vt++) { + + for (ot = 0; ot < config->num_output; ot++) { + this_tile = &config->output[ot]->tile_info; + + if (this_tile->group_id != tile_info->group_id) + continue; + + if (this_tile->tile_h_loc != ht || + this_tile->tile_v_loc != vt) + continue; + + monitor->outputs[output_num] = config->output[ot]->randr_output->id; + output_num++; + + } + + } + } + + ret = RRMonitorAdd(serverClient, pScreen, monitor); + if (ret) { + RRMonitorFree(monitor); + return; + } + } +} + static Bool xf86RandR12CreateScreenResources12(ScreenPtr pScreen) { @@ -1577,6 +1641,8 @@ xf86RandR12CreateScreenResources12(ScreenPtr pScreen) RRScreenSetSizeRange(pScreen, config->minWidth, config->minHeight, config->maxWidth, config->maxHeight); + + xf86RandR12CreateMonitors(pScreen); return TRUE; } diff --git a/hw/xfree86/parser/Configint.h b/hw/xfree86/parser/Configint.h index 31035ae2d..e5fa6cec2 100644 --- a/hw/xfree86/parser/Configint.h +++ b/hw/xfree86/parser/Configint.h @@ -204,6 +204,8 @@ else\ "Multiple \"%s\" lines." #define MUST_BE_OCTAL_MSG \ "The number \"%d\" given in this section must be in octal (0xxx) format." +#define GPU_DEVICE_TOO_MANY \ +"More than %d GPU devices defined." /* Warning messages */ #define OBSOLETE_MSG \ diff --git a/hw/xfree86/parser/Screen.c b/hw/xfree86/parser/Screen.c index 9d8eda277..b5b454ff4 100644 --- a/hw/xfree86/parser/Screen.c +++ b/hw/xfree86/parser/Screen.c @@ -211,6 +211,7 @@ static xf86ConfigSymTabRec ScreenTab[] = { {DEFAULTFBBPP, "defaultfbbpp"}, {VIRTUAL, "virtual"}, {OPTION, "option"}, + {GDEVICE, "gpudevice"}, {-1, ""}, }; @@ -270,6 +271,13 @@ xf86parseScreenSection(void) Error(QUOTE_MSG, "Device"); ptr->scrn_device_str = xf86_lex_val.str; break; + case GDEVICE: + if (xf86getSubToken(&(ptr->scrn_comment)) != STRING) + Error(QUOTE_MSG, "GPUDevice"); + if (ptr->num_gpu_devices == CONF_MAXGPUDEVICES) + Error(GPU_DEVICE_TOO_MANY, CONF_MAXGPUDEVICES); + ptr->scrn_gpu_device_str[ptr->num_gpu_devices++] = xf86_lex_val.str; + break; case MONITOR: if (xf86getSubToken(&(ptr->scrn_comment)) != STRING) Error(QUOTE_MSG, "Monitor"); @@ -342,7 +350,7 @@ xf86printScreenSection(FILE * cf, XF86ConfScreenPtr ptr) XF86ConfAdaptorLinkPtr aptr; XF86ConfDisplayPtr dptr; XF86ModePtr mptr; - + int i; while (ptr) { fprintf(cf, "Section \"Screen\"\n"); if (ptr->scrn_comment) @@ -353,6 +361,9 @@ xf86printScreenSection(FILE * cf, XF86ConfScreenPtr ptr) fprintf(cf, "\tDriver \"%s\"\n", ptr->scrn_obso_driver); if (ptr->scrn_device_str) fprintf(cf, "\tDevice \"%s\"\n", ptr->scrn_device_str); + for (i = 0; i < ptr->num_gpu_devices; i++) + if (ptr->scrn_gpu_device_str[i]) + fprintf(cf, "\tGPUDevice \"%s\"\n", ptr->scrn_gpu_device_str[i]); if (ptr->scrn_monitor_str) fprintf(cf, "\tMonitor \"%s\"\n", ptr->scrn_monitor_str); if (ptr->scrn_defaultdepth) @@ -426,11 +437,13 @@ void xf86freeScreenList(XF86ConfScreenPtr ptr) { XF86ConfScreenPtr prev; - + int i; while (ptr) { TestFree(ptr->scrn_identifier); TestFree(ptr->scrn_monitor_str); TestFree(ptr->scrn_device_str); + for (i = 0; i < ptr->num_gpu_devices; i++) + TestFree(ptr->scrn_gpu_device_str[i]); TestFree(ptr->scrn_comment); xf86optionListFree(ptr->scrn_option_lst); xf86freeAdaptorLinkList(ptr->scrn_adaptor_lst); @@ -487,6 +500,7 @@ xf86validateScreen(XF86ConfigPtr p) XF86ConfScreenPtr screen = p->conf_screen_lst; XF86ConfMonitorPtr monitor; XF86ConfAdaptorLinkPtr adaptor; + int i; while (screen) { if (screen->scrn_obso_driver && !screen->scrn_identifier) @@ -505,6 +519,10 @@ xf86validateScreen(XF86ConfigPtr p) screen->scrn_device = xf86findDevice(screen->scrn_device_str, p->conf_device_lst); + for (i = 0; i < screen->num_gpu_devices; i++) { + screen->scrn_gpu_devices[i] = + xf86findDevice(screen->scrn_gpu_device_str[i], p->conf_device_lst); + } adaptor = screen->scrn_adaptor_lst; while (adaptor) { adaptor->al_adaptor = diff --git a/hw/xfree86/parser/xf86Parser.h b/hw/xfree86/parser/xf86Parser.h index 43e17550c..b3a50e52f 100644 --- a/hw/xfree86/parser/xf86Parser.h +++ b/hw/xfree86/parser/xf86Parser.h @@ -259,6 +259,7 @@ typedef struct { XF86ConfVideoAdaptorPtr al_adaptor; } XF86ConfAdaptorLinkRec, *XF86ConfAdaptorLinkPtr; +#define CONF_MAXGPUDEVICES 4 typedef struct { GenericListRec list; const char *scrn_identifier; @@ -276,6 +277,10 @@ typedef struct { char *scrn_comment; int scrn_virtualX, scrn_virtualY; char *match_seat; + + int num_gpu_devices; + const char *scrn_gpu_device_str[CONF_MAXGPUDEVICES]; + XF86ConfDevicePtr scrn_gpu_devices[CONF_MAXGPUDEVICES]; } XF86ConfScreenRec, *XF86ConfScreenPtr; typedef struct { diff --git a/hw/xfree86/parser/xf86tokens.h b/hw/xfree86/parser/xf86tokens.h index 9c44970ea..bbd6b90d1 100644 --- a/hw/xfree86/parser/xf86tokens.h +++ b/hw/xfree86/parser/xf86tokens.h @@ -143,6 +143,7 @@ typedef enum { /* Screen tokens */ OBSDRIVER, MDEVICE, + GDEVICE, MONITOR, SCREENNO, DEFAULTDEPTH, diff --git a/randr/randrstr.h b/randr/randrstr.h index 438a52aeb..03974fd4f 100644 --- a/randr/randrstr.h +++ b/randr/randrstr.h @@ -1016,6 +1016,15 @@ RRMonitorFreeList(RRMonitorPtr monitors, int nmon); void RRMonitorClose(ScreenPtr screen); +RRMonitorPtr +RRMonitorAlloc(int noutput); + +int +RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor); + +void +RRMonitorFree(RRMonitorPtr monitor); + int ProcRRGetMonitors(ClientPtr client); diff --git a/randr/rrmonitor.c b/randr/rrmonitor.c index c4bb617b1..05285ddfd 100644 --- a/randr/rrmonitor.c +++ b/randr/rrmonitor.c @@ -389,13 +389,13 @@ RRMonitorCountList(ScreenPtr screen) return nmon; } -static void +void RRMonitorFree(RRMonitorPtr monitor) { free(monitor); } -static RRMonitorPtr +RRMonitorPtr RRMonitorAlloc(int noutput) { RRMonitorPtr monitor; @@ -451,7 +451,7 @@ RRMonitorMatchesOutputName(ScreenPtr screen, Atom name) return FALSE; } -static int +int RRMonitorAdd(ClientPtr client, ScreenPtr screen, RRMonitorPtr monitor) { rrScrPrivPtr pScrPriv = rrGetScrPriv(screen); |