📄 xf86crtc.c
字号:
scrn->virtualY = height; /* * Make sure the configuration isn't too small. */ if (width < config->minWidth || height < config->minHeight) return FALSE; /* * Limit the crtc config to virtual[XY] if the driver can't grow the * desktop. */ if (!canGrow) { xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight, width, height); } /* Mirror output modes to scrn mode list */ xf86SetScrnInfoModes (scrn); xfree (crtcs); xfree (modes); return TRUE;}/* * Using the desired mode information in each crtc, set * modes (used in EnterVT functions, or at server startup) */_X_EXPORT Boolxf86SetDesiredModes (ScrnInfoPtr scrn){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int c, o; /* * Turn off everything so mode setting is done * with hardware in a consistent state */ for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; (*output->funcs->dpms)(output, DPMSModeOff); } for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; crtc->funcs->dpms(crtc, DPMSModeOff); memset(&crtc->mode, 0, sizeof(crtc->mode)); } for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; xf86OutputPtr output = NULL; int o; if (config->output[config->compat_output]->crtc == crtc) output = config->output[config->compat_output]; else { for (o = 0; o < config->num_output; o++) if (config->output[o]->crtc == crtc) { output = config->output[o]; break; } } /* * Skip disabled crtcs */ if (!output) continue; /* Mark that we'll need to re-set the mode for sure */ memset(&crtc->mode, 0, sizeof(crtc->mode)); if (!crtc->desiredMode.CrtcHDisplay) { DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode); if (!mode) return FALSE; crtc->desiredMode = *mode; crtc->desiredRotation = RR_Rotate_0; crtc->desiredX = 0; crtc->desiredY = 0; } if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) return FALSE; } xf86DisableUnusedFunctions(scrn); return TRUE;}/** * In the current world order, there are lists of modes per output, which may * or may not include the mode that was asked to be set by XFree86's mode * selection. Find the closest one, in the following preference order: * * - Equality * - Closer in size to the requested mode, but no larger * - Closer in refresh rate to the requested mode. */_X_EXPORT DisplayModePtrxf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired){ DisplayModePtr best = NULL, scan = NULL; for (scan = output->probed_modes; scan != NULL; scan = scan->next) { /* If there's an exact match, we're done. */ if (xf86ModesEqual(scan, desired)) { best = desired; break; } /* Reject if it's larger than the desired mode. */ if (scan->HDisplay > desired->HDisplay || scan->VDisplay > desired->VDisplay) { continue; } /* * If we haven't picked a best mode yet, use the first * one in the size range */ if (best == NULL) { best = scan; continue; } /* Find if it's closer to the right size than the current best * option. */ if ((scan->HDisplay > best->HDisplay && scan->VDisplay >= best->VDisplay) || (scan->HDisplay >= best->HDisplay && scan->VDisplay > best->VDisplay)) { best = scan; continue; } /* Find if it's still closer to the right refresh than the current * best resolution. */ if (scan->HDisplay == best->HDisplay && scan->VDisplay == best->VDisplay && (fabs(scan->VRefresh - desired->VRefresh) < fabs(best->VRefresh - desired->VRefresh))) { best = scan; } } return best;}/** * When setting a mode through XFree86-VidModeExtension or XFree86-DGA, * take the specified mode and apply it to the crtc connected to the compat * output. Then, find similar modes for the other outputs, as with the * InitialConfiguration code above. The goal is to clone the desired * mode across all outputs that are currently active. */_X_EXPORT Boolxf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); Bool ok = TRUE; xf86OutputPtr compat_output = config->output[config->compat_output]; DisplayModePtr compat_mode; int c; /* * Let the compat output drive the final mode selection */ compat_mode = xf86OutputFindClosestMode (compat_output, desired); if (compat_mode) desired = compat_mode; for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; DisplayModePtr crtc_mode = NULL; int o; if (!crtc->enabled) continue; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; DisplayModePtr output_mode; /* skip outputs not on this crtc */ if (output->crtc != crtc) continue; if (crtc_mode) { output_mode = xf86OutputFindClosestMode (output, crtc_mode); if (output_mode != crtc_mode) output->crtc = NULL; } else crtc_mode = xf86OutputFindClosestMode (output, desired); } if (!crtc_mode) { crtc->enabled = FALSE; continue; } if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0)) ok = FALSE; else { crtc->desiredMode = *crtc_mode; crtc->desiredRotation = rotation; crtc->desiredX = 0; crtc->desiredY = 0; } } xf86DisableUnusedFunctions(pScrn);#if RANDR_12_INTERFACE xf86RandR12TellChanged (pScrn->pScreen);#endif return ok;}/** * Set the DPMS power mode of all outputs and CRTCs. * * If the new mode is off, it will turn off outputs and then CRTCs. * Otherwise, it will affect CRTCs before outputs. */_X_EXPORT voidxf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int i; if (!scrn->vtSema) return; if (mode == DPMSModeOff) { for (i = 0; i < config->num_output; i++) { xf86OutputPtr output = config->output[i]; if (output->crtc != NULL) (*output->funcs->dpms) (output, mode); } } for (i = 0; i < config->num_crtc; i++) { xf86CrtcPtr crtc = config->crtc[i]; if (crtc->enabled) (*crtc->funcs->dpms) (crtc, mode); } if (mode != DPMSModeOff) { for (i = 0; i < config->num_output; i++) { xf86OutputPtr output = config->output[i]; if (output->crtc != NULL) (*output->funcs->dpms) (output, mode); } }}/** * Implement the screensaver by just calling down into the driver DPMS hooks. * * Even for monitors with no DPMS support, by the definition of our DPMS hooks, * the outputs will still get disabled (blanked). */_X_EXPORT Boolxf86SaveScreen(ScreenPtr pScreen, int mode){ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; if (xf86IsUnblank(mode)) xf86DPMSSet(pScrn, DPMSModeOn, 0); else xf86DPMSSet(pScrn, DPMSModeOff, 0); return TRUE;}/** * Disable all inactive crtcs and outputs */_X_EXPORT voidxf86DisableUnusedFunctions(ScrnInfoPtr pScrn){ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int o, c; for (o = 0; o < xf86_config->num_output; o++) { xf86OutputPtr output = xf86_config->output[o]; if (!output->crtc) (*output->funcs->dpms)(output, DPMSModeOff); } for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; if (!crtc->enabled) { crtc->funcs->dpms(crtc, DPMSModeOff); memset(&crtc->mode, 0, sizeof(crtc->mode)); } }}#ifdef RANDR_12_INTERFACE#define EDID_ATOM_NAME "EDID_DATA"/** * Set the RandR EDID property */static voidxf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len){ Atom edid_atom = MakeAtom(EDID_ATOM_NAME, sizeof(EDID_ATOM_NAME) - 1, TRUE); /* This may get called before the RandR resources have been created */ if (output->randr_output == NULL) return; if (data_len != 0) { RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8, PropModeReplace, data_len, data, FALSE, TRUE); } else { RRDeleteOutputProperty(output->randr_output, edid_atom); }}#endif/** * Set the EDID information for the specified output */_X_EXPORT voidxf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon){ ScrnInfoPtr scrn = output->scrn; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int i;#ifdef RANDR_12_INTERFACE int size;#endif if (output->MonInfo != NULL) xfree(output->MonInfo); output->MonInfo = edid_mon; if (config->debug_modes) { xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); xf86PrintEDID(edid_mon); } /* Set the DDC properties for the 'compat' output */ if (output == config->output[config->compat_output]) xf86SetDDCproperties(scrn, edid_mon);#ifdef RANDR_12_INTERFACE /* Set the RandR output properties */ size = 0; if (edid_mon) { if (edid_mon->ver.version == 1) size = 128; else if (edid_mon->ver.version == 2) size = 256; } xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size);#endif if (edid_mon) { /* Pull out a phyiscal size from a detailed timing if available. */ for (i = 0; i < 4; i++) { if (edid_mon->det_mon[i].type == DT && edid_mon->det_mon[i].section.d_timings.h_size != 0 && edid_mon->det_mon[i].section.d_timings.v_size != 0) { output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size; output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size; break; } } /* if no mm size is available from a detailed timing, check the max size field */ if ((!output->mm_width || !output->mm_height) && (edid_mon->features.hsize && edid_mon->features.vsize)) { output->mm_width = edid_mon->features.hsize * 10; output->mm_height = edid_mon->features.vsize * 10; } }}/** * Return the list of modes supported by the EDID information * stored in 'output' */_X_EXPORT DisplayModePtrxf86OutputGetEDIDModes (xf86OutputPtr output){ ScrnInfoPtr scrn = output->scrn; xf86MonPtr edid_mon = output->MonInfo; if (!edid_mon) return NULL; return xf86DDCGetModes(scrn->scrnIndex, edid_mon);}_X_EXPORT xf86MonPtrxf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus){ ScrnInfoPtr scrn = output->scrn; return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);}static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D", "DVI-A", "Composite", "S-Video", "Component", "LFP", "Proprietary" };_X_EXPORT char *xf86ConnectorGetName(xf86ConnectorType connector){ return _xf86ConnectorNames[connector];}static voidx86_crtc_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b){ dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0;}static voidx86_crtc_box(xf86CrtcPtr crtc, BoxPtr crtc_box){ if (crtc->enabled) { crtc_box->x1 = crtc->x; crtc_box->x2 = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation); crtc_box->y1 = crtc->y; crtc_box->y2 = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation); } else crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0;}static intxf86_crtc_box_area(BoxPtr box){ return (int) (box->x2 - box->x1) * (int) (box->y2 - box->y1);}/* * Return the crtc covering 'box'. If two crtcs cover a portion of * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc * with greater coverage */static xf86CrtcPtrxf86_covering_crtc(ScrnInfoPtr pScrn, BoxPtr box, xf86CrtcPtr desired, BoxPtr crtc_box_ret){ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc, best_crtc; int coverage, best_coverage; int c; BoxRec crtc_box, cover_box; best_crtc = NULL; best_coverage = 0; crtc_box_ret->x1 = 0; crtc_box_ret->x2 = 0; crtc_box_ret->y1 = 0; crtc_box_ret->y2 = 0; for (c = 0; c < xf86_config->num_crtc; c++) { crtc = xf86_config->crtc[c]; x86_crtc_box(crtc, &crtc_box); x86_crtc_box_intersect(&cover_box, &crtc_box, box); coverage = xf86_crtc_box_area(&cover_box); if (coverage && crtc == desired) { *crtc_box_ret = crtc_box; return crtc; } else if (coverage > best_coverage) { *crtc_box_ret = crtc_box; best_crtc = crtc; best_coverage = coverage; } } return best_crtc;}/* * For overlay video, compute the relevant CRTC and * clip video to that */_X_EXPORT Boolxf86_crtc_clip_video_helper(ScrnInfoPtr pScrn, xf86CrtcPtr *crtc_ret, xf86CrtcPtr desired_crtc, BoxPtr dst, INT32 *xa, INT32 *xb, INT32 *ya, INT32 *yb, RegionPtr reg, INT32 width, INT32 height){ Bool ret; RegionRec crtc_region_local; RegionPtr crtc_region = reg; if (crtc_ret) { BoxRec crtc_box; xf86CrtcPtr crtc = xf86_covering_crtc(pScrn, dst, desired_crtc, &crtc_box); if (crtc) { REGION_INIT (pScreen, &crtc_region_local, &crtc_box, 1); crtc_region = &crtc_region_local; REGION_INTERSECT (pScreen, crtc_region, crtc_region, reg); } *crtc_ret = crtc; } ret = xf86XVClipVideoHelper(dst, xa, xb, ya, yb, crtc_region, width, height); if (crtc_region != reg) REGION_UNINIT (pScreen, &crtc_region_local); return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -