📄 xf86crtc.c
字号:
* function would do this work by itself. */static voidxf86PruneDuplicateMonitorModes (MonPtr Monitor){ DisplayModePtr master, clone, next; for (master = Monitor->Modes; master && master != Monitor->Last; master = master->next) { for (clone = master->next; clone && clone != Monitor->Modes; clone = next) { next = clone->next; if (xf86ModesEqual (master, clone)) { if (Monitor->Last == clone) Monitor->Last = clone->prev; xf86DeleteMode (&Monitor->Modes, clone); } } }}/** Return - 0 + if a should be earlier, same or later than b in list */static intxf86ModeCompare (DisplayModePtr a, DisplayModePtr b){ int diff; diff = ((b->type & M_T_PREFERRED) != 0) - ((a->type & M_T_PREFERRED) != 0); if (diff) return diff; diff = b->HDisplay * b->VDisplay - a->HDisplay * a->VDisplay; if (diff) return diff; diff = b->Clock - a->Clock; return diff;}/** * Insertion sort input in-place and return the resulting head */static DisplayModePtrxf86SortModes (DisplayModePtr input){ DisplayModePtr output = NULL, i, o, n, *op, prev; /* sort by preferred status and pixel area */ while (input) { i = input; input = input->next; for (op = &output; (o = *op); op = &o->next) if (xf86ModeCompare (o, i) > 0) break; i->next = *op; *op = i; } /* prune identical modes */ for (o = output; o && (n = o->next); o = n) { if (!strcmp (o->name, n->name) && xf86ModesEqual (o, n)) { o->next = n->next; xfree (n->name); xfree (n); n = o; } } /* hook up backward links */ prev = NULL; for (o = output; o; o = o->next) { o->prev = prev; prev = o; } return output;}_X_EXPORT voidxf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o; /* When canGrow was TRUE in the initial configuration we have to * compare against the maximum values so that we don't drop modes. * When canGrow was FALSE, the maximum values would have been clamped * anyway. */ if (maxX == 0 || maxY == 0) { maxX = config->maxWidth; maxY = config->maxHeight; } /* Elide duplicate modes before defaulting code uses them */ xf86PruneDuplicateMonitorModes (scrn->monitor); /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; DisplayModePtr mode; DisplayModePtr config_modes = NULL, output_modes, default_modes; char *preferred_mode; xf86MonPtr edid_monitor; XF86ConfMonitorPtr conf_monitor; MonRec mon_rec; int min_clock = 0; int max_clock = 0; double clock; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) xf86DeleteMode(&output->probed_modes, output->probed_modes); /* * Check connection status */ output->status = (*output->funcs->detect)(output); if (output->status == XF86OutputStatusDisconnected) { xf86OutputSetEDID (output, NULL); continue; } memset (&mon_rec, '\0', sizeof (mon_rec)); conf_monitor = output->conf_monitor; if (conf_monitor) { int i; for (i = 0; i < conf_monitor->mon_n_hsync; i++) { mon_rec.hsync[mon_rec.nHsync].lo = conf_monitor->mon_hsync[i].lo; mon_rec.hsync[mon_rec.nHsync].hi = conf_monitor->mon_hsync[i].hi; mon_rec.nHsync++; sync_source = sync_config; } for (i = 0; i < conf_monitor->mon_n_vrefresh; i++) { mon_rec.vrefresh[mon_rec.nVrefresh].lo = conf_monitor->mon_vrefresh[i].lo; mon_rec.vrefresh[mon_rec.nVrefresh].hi = conf_monitor->mon_vrefresh[i].hi; mon_rec.nVrefresh++; sync_source = sync_config; } config_modes = xf86GetMonitorModes (scrn, conf_monitor); } output_modes = (*output->funcs->get_modes) (output); edid_monitor = output->MonInfo; if (edid_monitor) { int i; Bool set_hsync = mon_rec.nHsync == 0; Bool set_vrefresh = mon_rec.nVrefresh == 0; for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++) { if (edid_monitor->det_mon[i].type == DS_RANGES) { struct monitor_ranges *ranges = &edid_monitor->det_mon[i].section.ranges; if (set_hsync && ranges->max_h) { mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h; mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h; mon_rec.nHsync++; if (sync_source == sync_default) sync_source = sync_edid; } if (set_vrefresh && ranges->max_v) { mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v; mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v; mon_rec.nVrefresh++; if (sync_source == sync_default) sync_source = sync_edid; } if (ranges->max_clock > max_clock) max_clock = ranges->max_clock; } } } if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, OPTUNITS_KHZ, &clock)) min_clock = (int) clock; if (xf86GetOptValFreq (output->options, OPTION_MAX_CLOCK, OPTUNITS_KHZ, &clock)) max_clock = (int) clock; /* * These limits will end up setting a 1024x768@60Hz mode by default, * which seems like a fairly good mode to use when nothing else is * specified */ if (mon_rec.nHsync == 0) { mon_rec.hsync[0].lo = 31.0; mon_rec.hsync[0].hi = 55.0; mon_rec.nHsync = 1; } if (mon_rec.nVrefresh == 0) { mon_rec.vrefresh[0].lo = 58.0; mon_rec.vrefresh[0].hi = 62.0; mon_rec.nVrefresh = 1; } default_modes = xf86GetDefaultModes (output->interlaceAllowed, output->doubleScanAllowed); if (sync_source == sync_config) { /* * Check output and config modes against sync range from config file */ xf86ValidateModesSync (scrn, output_modes, &mon_rec); xf86ValidateModesSync (scrn, config_modes, &mon_rec); } /* * Check default modes against sync range */ xf86ValidateModesSync (scrn, default_modes, &mon_rec); /* * Check default modes against monitor max clock */ if (max_clock) xf86ValidateModesClocks(scrn, default_modes, &min_clock, &max_clock, 1); output->probed_modes = NULL; output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); output->probed_modes = xf86ModesAdd (output->probed_modes, output_modes); output->probed_modes = xf86ModesAdd (output->probed_modes, default_modes); /* * Check all modes against max size */ if (maxX && maxY) xf86ValidateModesSize (scrn, output->probed_modes, maxX, maxY, 0); /* * Check all modes against output */ for (mode = output->probed_modes; mode != NULL; mode = mode->next) if (mode->status == MODE_OK) mode->status = (*output->funcs->mode_valid)(output, mode); xf86PruneInvalidModes(scrn, &output->probed_modes, config->debug_modes); output->probed_modes = xf86SortModes (output->probed_modes); /* Check for a configured preference for a particular mode */ preferred_mode = xf86GetOptValString (output->options, OPTION_PREFERRED_MODE); if (preferred_mode) { for (mode = output->probed_modes; mode; mode = mode->next) { if (!strcmp (preferred_mode, mode->name)) { if (mode != output->probed_modes) { if (mode->prev) mode->prev->next = mode->next; if (mode->next) mode->next->prev = mode->prev; mode->next = output->probed_modes; output->probed_modes->prev = mode; mode->prev = NULL; output->probed_modes = mode; } mode->type |= M_T_PREFERRED; } else mode->type &= ~M_T_PREFERRED; } } output->initial_rotation = xf86OutputInitialRotation (output); if (config->debug_modes) { if (output->probed_modes != NULL) { xf86DrvMsg(scrn->scrnIndex, X_INFO, "Printing probed modes for output %s\n", output->name); } else { xf86DrvMsg(scrn->scrnIndex, X_INFO, "No remaining probed modes for output %s\n", output->name); } } for (mode = output->probed_modes; mode != NULL; mode = mode->next) { /* The code to choose the best mode per pipe later on will require * VRefresh to be set. */ mode->VRefresh = xf86ModeVRefresh(mode); xf86SetModeCrtc(mode, INTERLACE_HALVE_V); if (config->debug_modes) xf86PrintModeline(scrn->scrnIndex, mode); } }}/** * Copy one of the output mode lists to the ScrnInfo record *//* XXX where does this function belong? Here? */_X_EXPORT voidxf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);_X_EXPORT voidxf86SetScrnInfoModes (ScrnInfoPtr scrn){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); xf86OutputPtr output; xf86CrtcPtr crtc; DisplayModePtr last, mode; output = config->output[config->compat_output]; if (!output->crtc) { int o; output = NULL; for (o = 0; o < config->num_output; o++) if (config->output[o]->crtc) { config->compat_output = o; output = config->output[o]; break; } /* no outputs are active, punt and leave things as they are */ if (!output) return; } crtc = output->crtc; /* Clear any existing modes from scrn->modes */ while (scrn->modes != NULL) xf86DeleteMode(&scrn->modes, scrn->modes); /* Set scrn->modes to the mode list for the 'compat' output */ scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); for (mode = scrn->modes; mode; mode = mode->next) if (xf86ModesEqual (mode, &crtc->desiredMode)) break; if (scrn->modes != NULL) { /* For some reason, scrn->modes is circular, unlike the other mode * lists. How great is that? */ for (last = scrn->modes; last && last->next; last = last->next) ; last->next = scrn->modes; scrn->modes->prev = last; if (mode) { while (scrn->modes != mode) scrn->modes = scrn->modes->next; } } scrn->currentMode = scrn->modes;}/** * Construct default screen configuration * * Given auto-detected (and, eventually, configured) values, * construct a usable configuration for the system * * canGrow indicates that the driver can resize the screen to larger than its * initially configured size via the config->funcs->resize hook. If TRUE, this * function will set virtualX and virtualY to match the initial configuration * and leave config->max{Width,Height} alone. If FALSE, it will bloat * virtual[XY] to include the largest modes and set config->max{Width,Height} * accordingly. */_X_EXPORT Boolxf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o, c; DisplayModePtr target_mode = NULL; Rotation target_rotation = RR_Rotate_0; xf86CrtcPtr *crtcs; DisplayModePtr *modes; Bool *enabled; int width; int height; /* Set up the device options */ config->options = xnfalloc (sizeof (xf86DeviceOptions)); memcpy (config->options, xf86DeviceOptions, sizeof (xf86DeviceOptions)); xf86ProcessOptions (scrn->scrnIndex, scrn->options, config->options); config->debug_modes = xf86ReturnOptValBool (config->options, OPTION_MODEDEBUG, FALSE); if (scrn->display->virtualX) width = scrn->display->virtualX; else width = config->maxWidth; if (scrn->display->virtualY) height = scrn->display->virtualY; else height = config->maxHeight; xf86ProbeOutputModes (scrn, width, height); crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); enabled = xnfcalloc (config->num_output, sizeof (Bool)); for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; modes[o] = NULL; enabled[o] = xf86OutputEnabled (output); } /* * Let outputs with preferred modes drive screen size */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; if (enabled[o] && xf86OutputHasPreferredMode (output, width, height)) { target_mode = xf86DefaultMode (output, width, height); target_rotation = output->initial_rotation; if (target_mode) { modes[o] = target_mode; config->compat_output = o; break; } } } if (!target_mode) { for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; if (enabled[o]) { target_mode = xf86DefaultMode (output, width, height); target_rotation = output->initial_rotation; if (target_mode) { modes[o] = target_mode; config->compat_output = o; break; } } } } for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; if (enabled[o]) { if (!modes[o]) modes[o] = xf86ClosestMode (output, target_mode, target_rotation, width, height); if (!modes[o]) xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Output %s enabled but has no modes\n", output->name); else xf86DrvMsg (scrn->scrnIndex, X_INFO, "Output %s using initial mode %s\n", output->name, modes[o]->name); } } /* * Set the position of each output */ if (!xf86InitialOutputPositions (scrn, modes)) { xfree (crtcs); xfree (modes); return FALSE; } /* * Assign CRTCs to fit output configuration */ if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) { xfree (crtcs); xfree (modes); return FALSE; } /* XXX override xf86 common frame computation code */ scrn->display->frameX0 = 0; scrn->display->frameY0 = 0; for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; crtc->enabled = FALSE; memset (&crtc->desiredMode, '\0', sizeof (crtc->desiredMode)); } /* * Set initial configuration */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; DisplayModePtr mode = modes[o]; xf86CrtcPtr crtc = crtcs[o]; if (mode && crtc) { crtc->desiredMode = *mode; crtc->desiredRotation = output->initial_rotation; crtc->desiredX = output->initial_x; crtc->desiredY = output->initial_y; crtc->enabled = TRUE; crtc->x = output->initial_x; crtc->y = output->initial_y; output->crtc = crtc; } } if (scrn->display->virtualX == 0) { /* * Expand virtual size to cover the current config and potential mode * switches, if the driver can't enlarge the screen later. */ xf86DefaultScreenLimits (scrn, &width, &height, canGrow); scrn->display->virtualX = width; scrn->display->virtualY = height; } if (width > scrn->virtualX) scrn->virtualX = width; if (height > scrn->virtualY)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -