📄 xf86crtc.c
字号:
/* * Copyright © 2006 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#ifdef HAVE_XORG_CONFIG_H#include <xorg-config.h>#else#ifdef HAVE_CONFIG_H#include <config.h>#endif#endif#include <stddef.h>#include <string.h>#include <stdio.h>#include "xf86.h"#include "xf86DDC.h"#include "xf86Crtc.h"#include "xf86Modes.h"#include "xf86RandR12.h"#include "X11/extensions/render.h"#define DPMS_SERVER#include "X11/extensions/dpms.h"#include "X11/Xatom.h"#ifdef RENDER#include "picturestr.h"#endif#include "xf86xv.h"/* * Initialize xf86CrtcConfig structure */int xf86CrtcConfigPrivateIndex = -1;_X_EXPORT voidxf86CrtcConfigInit (ScrnInfoPtr scrn, const xf86CrtcConfigFuncsRec *funcs){ xf86CrtcConfigPtr config; if (xf86CrtcConfigPrivateIndex == -1) xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); config = xnfcalloc (1, sizeof (xf86CrtcConfigRec)); config->funcs = funcs; scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;} _X_EXPORT voidxf86CrtcSetSizeRange (ScrnInfoPtr scrn, int minWidth, int minHeight, int maxWidth, int maxHeight){ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); config->minWidth = minWidth; config->minHeight = minHeight; config->maxWidth = maxWidth; config->maxHeight = maxHeight;}/* * Crtc functions */_X_EXPORT xf86CrtcPtrxf86CrtcCreate (ScrnInfoPtr scrn, const xf86CrtcFuncsRec *funcs){ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcPtr crtc, *crtcs; crtc = xcalloc (sizeof (xf86CrtcRec), 1); if (!crtc) return NULL; crtc->scrn = scrn; crtc->funcs = funcs;#ifdef RANDR_12_INTERFACE crtc->randr_crtc = NULL;#endif crtc->rotation = RR_Rotate_0; crtc->desiredRotation = RR_Rotate_0; if (xf86_config->crtc) crtcs = xrealloc (xf86_config->crtc, (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); else crtcs = xalloc ((xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); if (!crtcs) { xfree (crtc); return NULL; } xf86_config->crtc = crtcs; xf86_config->crtc[xf86_config->num_crtc++] = crtc; return crtc;}_X_EXPORT voidxf86CrtcDestroy (xf86CrtcPtr crtc){ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); int c; (*crtc->funcs->destroy) (crtc); for (c = 0; c < xf86_config->num_crtc; c++) if (xf86_config->crtc[c] == crtc) { memmove (&xf86_config->crtc[c], &xf86_config->crtc[c+1], ((xf86_config->num_crtc - (c + 1)) * sizeof(void*))); xf86_config->num_crtc--; break; } xfree (crtc);}/** * Return whether any outputs are connected to the specified pipe */_X_EXPORT Boolxf86CrtcInUse (xf86CrtcPtr crtc){ ScrnInfoPtr pScrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int o; for (o = 0; o < xf86_config->num_output; o++) if (xf86_config->output[o]->crtc == crtc) return TRUE; return FALSE;}_X_EXPORT voidxf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen){#ifdef RENDER int subpixel_order = SubPixelUnknown; Bool has_none = FALSE; ScrnInfoPtr scrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int c, o; for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; for (o = 0; o < xf86_config->num_output; o++) { xf86OutputPtr output = xf86_config->output[o]; if (output->crtc == crtc) { switch (output->subpixel_order) { case SubPixelNone: has_none = TRUE; break; case SubPixelUnknown: break; default: subpixel_order = output->subpixel_order; break; } } if (subpixel_order != SubPixelUnknown) break; } if (subpixel_order != SubPixelUnknown) { static const int circle[4] = { SubPixelHorizontalRGB, SubPixelVerticalRGB, SubPixelHorizontalBGR, SubPixelVerticalBGR, }; int rotate; int c; for (rotate = 0; rotate < 4; rotate++) if (crtc->rotation & (1 << rotate)) break; for (c = 0; c < 4; c++) if (circle[c] == subpixel_order) break; c = (c + rotate) & 0x3; if ((crtc->rotation & RR_Reflect_X) && !(c & 1)) c ^= 2; if ((crtc->rotation & RR_Reflect_Y) && (c & 1)) c ^= 2; subpixel_order = circle[c]; break; } } if (subpixel_order == SubPixelUnknown && has_none) subpixel_order = SubPixelNone; PictureSetSubpixelOrder (pScreen, subpixel_order);#endif}/** * Sets the given video mode on the given crtc */_X_EXPORT Boolxf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y){ ScrnInfoPtr scrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int i; Bool ret = FALSE; Bool didLock = FALSE; DisplayModePtr adjusted_mode; DisplayModeRec saved_mode; int saved_x, saved_y; Rotation saved_rotation; crtc->enabled = xf86CrtcInUse (crtc); if (!crtc->enabled) { /* XXX disable crtc? */ return TRUE; } adjusted_mode = xf86DuplicateMode(mode); didLock = crtc->funcs->lock (crtc); saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; saved_rotation = crtc->rotation; /* Update crtc values up front so the driver can rely on them for mode * setting. */ crtc->mode = *mode; crtc->x = x; crtc->y = y; crtc->rotation = rotation; /* XXX short-circuit changes to base location only */ /* Pass our mode to the outputs and the CRTC to give them a chance to * adjust it according to limitations or output properties, and also * a chance to reject the mode entirely. */ for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { goto done; } } if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { goto done; } if (!xf86CrtcRotate (crtc, mode, rotation)) { goto done; } /* Prepare the outputs and CRTCs before setting the mode. */ for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc != crtc) continue; /* Disable the output as the first thing we do. */ output->funcs->prepare(output); } crtc->funcs->prepare(crtc); /* Set up the DPLL and any output state that needs to adjust or depend * on the DPLL. */ crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y); for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) output->funcs->mode_set(output, mode, adjusted_mode); } /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ crtc->funcs->commit(crtc); for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; if (output->crtc == crtc) { output->funcs->commit(output);#ifdef RANDR_12_INTERFACE if (output->randr_output) RRPostPendingProperties (output->randr_output);#endif } } /* XXX free adjustedmode */ ret = TRUE; if (scrn->pScreen) xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);done: if (!ret) { crtc->x = saved_x; crtc->y = saved_y; crtc->rotation = saved_rotation; crtc->mode = saved_mode; } if (didLock) crtc->funcs->unlock (crtc); return ret;}/* * Output functions */extern XF86ConfigPtr xf86configptr;typedef enum { OPTION_PREFERRED_MODE, OPTION_POSITION, OPTION_BELOW, OPTION_RIGHT_OF, OPTION_ABOVE, OPTION_LEFT_OF, OPTION_ENABLE, OPTION_DISABLE, OPTION_MIN_CLOCK, OPTION_MAX_CLOCK, OPTION_IGNORE, OPTION_ROTATE,} OutputOpts;static OptionInfoRec xf86OutputOptions[] = { {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, {OPTION_ABOVE, "Above", OPTV_STRING, {0}, FALSE }, {OPTION_LEFT_OF, "LeftOf", OPTV_STRING, {0}, FALSE }, {OPTION_ENABLE, "Enable", OPTV_BOOLEAN, {0}, FALSE }, {OPTION_DISABLE, "Disable", OPTV_BOOLEAN, {0}, FALSE }, {OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE }, {OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE }, {OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE }, {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE }, {-1, NULL, OPTV_NONE, {0}, FALSE },};enum { OPTION_MODEDEBUG,};static OptionInfoRec xf86DeviceOptions[] = { {OPTION_MODEDEBUG, "ModeDebug", OPTV_STRING, {0}, FALSE }, {-1, NULL, OPTV_NONE, {0}, FALSE },};static voidxf86OutputSetMonitor (xf86OutputPtr output){ char *option_name; static const char monitor_prefix[] = "monitor-"; char *monitor; if (!output->name) return; if (output->options) xfree (output->options); output->options = xnfalloc (sizeof (xf86OutputOptions)); memcpy (output->options, xf86OutputOptions, sizeof (xf86OutputOptions)); option_name = xnfalloc (strlen (monitor_prefix) + strlen (output->name) + 1); strcpy (option_name, monitor_prefix); strcat (option_name, output->name); monitor = xf86findOptionValue (output->scrn->options, option_name); if (!monitor) monitor = output->name; else xf86MarkOptionUsedByName (output->scrn->options, option_name); xfree (option_name); output->conf_monitor = xf86findMonitor (monitor, xf86configptr->conf_monitor_lst); /* * Find the monitor section of the screen and use that */ if (!output->conf_monitor && output->use_screen_monitor) output->conf_monitor = xf86findMonitor (output->scrn->monitor->id, xf86configptr->conf_monitor_lst); if (output->conf_monitor) { xf86DrvMsg (output->scrn->scrnIndex, X_INFO, "Output %s using monitor section %s\n", output->name, output->conf_monitor->mon_identifier); xf86ProcessOptions (output->scrn->scrnIndex, output->conf_monitor->mon_option_lst, output->options); } else xf86DrvMsg (output->scrn->scrnIndex, X_INFO, "Output %s has no monitor section\n", output->name);}static Boolxf86OutputEnabled (xf86OutputPtr output){ Bool enable, disable; /* check to see if this output was enabled in the config file */ if (xf86GetOptValBool (output->options, OPTION_ENABLE, &enable) && enable) { xf86DrvMsg (output->scrn->scrnIndex, X_INFO, "Output %s enabled by config file\n", output->name); return TRUE; } /* or if this output was disabled in the config file */ if (xf86GetOptValBool (output->options, OPTION_DISABLE, &disable) && disable) { xf86DrvMsg (output->scrn->scrnIndex, X_INFO, "Output %s disabled by config file\n", output->name); return FALSE; } /* otherwise, enable if it is not disconnected */ enable = output->status != XF86OutputStatusDisconnected; xf86DrvMsg (output->scrn->scrnIndex, X_INFO, "Output %s %sconnected\n", output->name, enable ? "" : "dis"); return enable;}static Boolxf86OutputIgnored (xf86OutputPtr output){ return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);}static char *direction[4] = { "normal", "left", "inverted", "right"};static Rotationxf86OutputInitialRotation (xf86OutputPtr output){ char *rotate_name = xf86GetOptValString (output->options, OPTION_ROTATE); int i; if (!rotate_name) return RR_Rotate_0; for (i = 0; i < 4; i++) if (xf86nameCompare (direction[i], rotate_name) == 0) return (1 << i); return RR_Rotate_0;}_X_EXPORT xf86OutputPtrxf86OutputCreate (ScrnInfoPtr scrn, const xf86OutputFuncsRec *funcs, const char *name){ xf86OutputPtr output, *outputs; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int len; if (name) len = strlen (name) + 1; else len = 0; output = xcalloc (sizeof (xf86OutputRec) + len, 1); if (!output) return NULL; output->scrn = scrn; output->funcs = funcs; if (name) { output->name = (char *) (output + 1); strcpy (output->name, name); } output->subpixel_order = SubPixelUnknown; /* * Use the old per-screen monitor section for the first output */ output->use_screen_monitor = (xf86_config->num_output == 0);#ifdef RANDR_12_INTERFACE output->randr_output = NULL;#endif if (name) { xf86OutputSetMonitor (output); if (xf86OutputIgnored (output)) { xfree (output); return FALSE; } } if (xf86_config->output) outputs = xrealloc (xf86_config->output, (xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); else outputs = xalloc ((xf86_config->num_output + 1) * sizeof (xf86OutputPtr)); if (!outputs) { xfree (output); return NULL; } xf86_config->output = outputs; xf86_config->output[xf86_config->num_output++] = output; return output;}_X_EXPORT Boolxf86OutputRename (xf86OutputPtr output, const char *name){ int len = strlen(name) + 1; char *newname = xalloc (len); if (!newname) return FALSE; /* so sorry... */ strcpy (newname, name); if (output->name && output->name != (char *) (output + 1)) xfree (output->name); output->name = newname;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -