📄 xf86crtc.c
字号:
xf86OutputSetMonitor (output); if (xf86OutputIgnored (output)) return FALSE; return TRUE;}_X_EXPORT voidxf86OutputUseScreenMonitor (xf86OutputPtr output, Bool use_screen_monitor){ if (use_screen_monitor != output->use_screen_monitor) { output->use_screen_monitor = use_screen_monitor; xf86OutputSetMonitor (output); }}_X_EXPORT voidxf86OutputDestroy (xf86OutputPtr output){ ScrnInfoPtr scrn = output->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int o; (*output->funcs->destroy) (output); while (output->probed_modes) xf86DeleteMode (&output->probed_modes, output->probed_modes); for (o = 0; o < xf86_config->num_output; o++) if (xf86_config->output[o] == output) { memmove (&xf86_config->output[o], &xf86_config->output[o+1], ((xf86_config->num_output - (o + 1)) * sizeof(void*))); xf86_config->num_output--; break; } if (output->name && output->name != (char *) (output + 1)) xfree (output->name); xfree (output);}/* * Called during CreateScreenResources to hook up RandR */static Boolxf86CrtcCreateScreenResources (ScreenPtr screen){ ScrnInfoPtr scrn = xf86Screens[screen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); screen->CreateScreenResources = config->CreateScreenResources; if (!(*screen->CreateScreenResources)(screen)) return FALSE; if (!xf86RandR12CreateScreenResources (screen)) return FALSE; return TRUE;}/* * Clean up config on server reset */static Boolxf86CrtcCloseScreen (int index, ScreenPtr screen){ ScrnInfoPtr scrn = xf86Screens[screen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o, c; screen->CloseScreen = config->CloseScreen; xf86RotateCloseScreen (screen); for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; output->randr_output = NULL; } for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; crtc->randr_crtc = NULL; } return screen->CloseScreen (index, screen);}/* * Called at ScreenInit time to set up */_X_EXPORT Boolxf86CrtcScreenInit (ScreenPtr screen){ ScrnInfoPtr scrn = xf86Screens[screen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int c; /* Rotation */ xf86DrvMsg(scrn->scrnIndex, X_INFO, "RandR 1.2 enabled, ignore the following RandR disabled message.\n"); xf86DisableRandR(); /* Disable old RandR extension support */ xf86RandR12Init (screen); /* support all rotations if every crtc has the shadow alloc funcs */ for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; if (!crtc->funcs->shadow_allocate || !crtc->funcs->shadow_create) break; } if (c == config->num_crtc) xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y); else xf86RandR12SetRotations (screen, RR_Rotate_0); /* Wrap CreateScreenResources so we can initialize the RandR code */ config->CreateScreenResources = screen->CreateScreenResources; screen->CreateScreenResources = xf86CrtcCreateScreenResources; config->CloseScreen = screen->CloseScreen; screen->CloseScreen = xf86CrtcCloseScreen; return TRUE;}static DisplayModePtrxf86DefaultMode (xf86OutputPtr output, int width, int height){ DisplayModePtr target_mode = NULL; DisplayModePtr mode; int target_diff = 0; int target_preferred = 0; int mm_height; mm_height = output->mm_height; if (!mm_height) mm_height = 203; /* 768 pixels at 96dpi */ /* * Pick a mode closest to 96dpi */ for (mode = output->probed_modes; mode; mode = mode->next) { int dpi; int preferred = (mode->type & M_T_PREFERRED) != 0; int diff; if (xf86ModeWidth (mode, output->initial_rotation) > width || xf86ModeHeight (mode, output->initial_rotation) > height) continue; /* yes, use VDisplay here, not xf86ModeHeight */ dpi = (mode->VDisplay * 254) / (mm_height * 10); diff = dpi - 96; diff = diff < 0 ? -diff : diff; if (target_mode == NULL || (preferred > target_preferred) || (preferred == target_preferred && diff < target_diff)) { target_mode = mode; target_diff = diff; target_preferred = preferred; } } return target_mode;}static DisplayModePtrxf86ClosestMode (xf86OutputPtr output, DisplayModePtr match, Rotation match_rotation, int width, int height){ DisplayModePtr target_mode = NULL; DisplayModePtr mode; int target_diff = 0; /* * Pick a mode closest to the specified mode */ for (mode = output->probed_modes; mode; mode = mode->next) { int dx, dy; int diff; if (xf86ModeWidth (mode, output->initial_rotation) > width || xf86ModeHeight (mode, output->initial_rotation) > height) continue; /* exact matches are preferred */ if (output->initial_rotation == match_rotation && xf86ModesEqual (mode, match)) return mode; dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation); dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation); diff = dx * dx + dy * dy; if (target_mode == NULL || diff < target_diff) { target_mode = mode; target_diff = diff; } } return target_mode;}static Boolxf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height){ DisplayModePtr mode; for (mode = output->probed_modes; mode; mode = mode->next) { if (xf86ModeWidth (mode, output->initial_rotation) > width || xf86ModeHeight (mode, output->initial_rotation) > height) continue; if (mode->type & M_T_PREFERRED) return TRUE; } return FALSE;}static intxf86PickCrtcs (ScrnInfoPtr scrn, xf86CrtcPtr *best_crtcs, DisplayModePtr *modes, int n, int width, int height){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int c, o; xf86OutputPtr output; xf86CrtcPtr crtc; xf86CrtcPtr *crtcs; xf86CrtcPtr best_crtc; int best_score; int score; int my_score; if (n == config->num_output) return 0; output = config->output[n]; /* * Compute score with this output disabled */ best_crtcs[n] = NULL; best_crtc = NULL; best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); if (modes[n] == NULL) return best_score; crtcs = xalloc (config->num_output * sizeof (xf86CrtcPtr)); if (!crtcs) return best_score; my_score = 1; /* Score outputs that are known to be connected higher */ if (output->status == XF86OutputStatusConnected) my_score++; /* Score outputs with preferred modes higher */ if (xf86OutputHasPreferredMode (output, width, height)) my_score++; /* * Select a crtc for this output and * then attempt to configure the remaining * outputs */ for (c = 0; c < config->num_crtc; c++) { if ((output->possible_crtcs & (1 << c)) == 0) continue; crtc = config->crtc[c]; /* * Check to see if some other output is * using this crtc */ for (o = 0; o < n; o++) if (best_crtcs[o] == crtc) break; if (o < n) { /* * If the two outputs desire the same mode, * see if they can be cloned */ if (xf86ModesEqual (modes[o], modes[n]) && config->output[0]->initial_rotation == config->output[n]->initial_rotation && config->output[o]->initial_x == config->output[n]->initial_x && config->output[o]->initial_y == config->output[n]->initial_y) { if ((output->possible_clones & (1 << o)) == 0) continue; /* nope, try next CRTC */ } else continue; /* different modes, can't clone */ } crtcs[n] = crtc; memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); if (score > best_score) { best_crtc = crtc; best_score = score; memcpy (best_crtcs, crtcs, config->num_output * sizeof (xf86CrtcPtr)); } } xfree (crtcs); return best_score;}/* * Compute the virtual size necessary to place all of the available * crtcs in the specified configuration. * * canGrow indicates that the driver can make the screen larger than its initial * configuration. If FALSE, this function will enlarge the screen to include * the largest available mode. */static voidxf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp, Bool canGrow){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int width = 0, height = 0; int o; int c; int s; for (c = 0; c < config->num_crtc; c++) { int crtc_width = 0, crtc_height = 0; xf86CrtcPtr crtc = config->crtc[c]; if (crtc->enabled) { crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation); crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation); } if (!canGrow) { for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; for (s = 0; s < config->num_crtc; s++) if (output->possible_crtcs & (1 << s)) { DisplayModePtr mode; for (mode = output->probed_modes; mode; mode = mode->next) { if (mode->HDisplay > crtc_width) crtc_width = mode->HDisplay; if (mode->VDisplay > crtc_width) crtc_width = mode->VDisplay; if (mode->VDisplay > crtc_height) crtc_height = mode->VDisplay; if (mode->HDisplay > crtc_height) crtc_height = mode->HDisplay; } } } } if (crtc_width > width) width = crtc_width; if (crtc_height > height) height = crtc_height; } if (config->maxWidth && width > config->maxWidth) width = config->maxWidth; if (config->maxHeight && height > config->maxHeight) height = config->maxHeight; if (config->minWidth && width < config->minWidth) width = config->minWidth; if (config->minHeight && height < config->minHeight) height = config->minHeight; *widthp = width; *heightp = height;}#define POSITION_UNSET -100000static Boolxf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o; int min_x, min_y; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; output->initial_x = output->initial_y = POSITION_UNSET; } /* * Loop until all outputs are set */ for (;;) { Bool any_set = FALSE; Bool keep_going = FALSE; for (o = 0; o < config->num_output; o++) { static const OutputOpts relations[] = { OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF }; xf86OutputPtr output = config->output[o]; xf86OutputPtr relative; char *relative_name; char *position; OutputOpts relation; int r; if (output->initial_x != POSITION_UNSET) continue; position = xf86GetOptValString (output->options, OPTION_POSITION); /* * Absolute position wins */ if (position) { int x, y; if (sscanf (position, "%d %d", &x, &y) == 2) { output->initial_x = x; output->initial_y = y; } else { xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Output %s position not of form \"x y\"\n", output->name); output->initial_x = output->initial_y = 0; } any_set = TRUE; continue; } /* * Next comes relative positions */ relation = 0; relative_name = NULL; for (r = 0; r < 4; r++) { relation = relations[r]; relative_name = xf86GetOptValString (output->options, relation); if (relative_name) break; } if (relative_name) { int or; relative = NULL; for (or = 0; or < config->num_output; or++) { xf86OutputPtr out_rel = config->output[or]; XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor; if (rel_mon) { if (xf86nameCompare (rel_mon->mon_identifier, relative_name) == 0) { relative = config->output[or]; break; } } if (strcmp (out_rel->name, relative_name) == 0) { relative = config->output[or]; break; } } if (!relative) { xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Cannot position output %s relative to unknown output %s\n", output->name, relative_name); output->initial_x = 0; output->initial_y = 0; any_set = TRUE; continue; } if (relative->initial_x == POSITION_UNSET) { keep_going = TRUE; continue; } output->initial_x = relative->initial_x; output->initial_y = relative->initial_y; switch (relation) { case OPTION_BELOW: output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation); break; case OPTION_RIGHT_OF: output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation); break; case OPTION_ABOVE: output->initial_y -= xf86ModeHeight (modes[or], relative->initial_rotation); break; case OPTION_LEFT_OF: output->initial_x -= xf86ModeWidth (modes[or], relative->initial_rotation); break; default: break; } any_set = TRUE; continue; } /* Nothing set, just stick them at 0,0 */ output->initial_x = 0; output->initial_y = 0; any_set = TRUE; } if (!keep_going) break; if (!any_set) { for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; if (output->initial_x == POSITION_UNSET) { xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Output position loop. Moving %s to 0,0\n", output->name); output->initial_x = output->initial_y = 0; break; } } } } /* * normalize positions */ min_x = 1000000; min_y = 1000000; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; if (output->initial_x < min_x) min_x = output->initial_x; if (output->initial_y < min_y) min_y = output->initial_y; } for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; output->initial_x -= min_x; output->initial_y -= min_y; } return TRUE;}/* * XXX walk the monitor mode list and prune out duplicates that * are inserted by xf86DDCMonitorSet. In an ideal world, that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -