Merge crtc/output-based mode selection code.

This code comes from the intel driver, so there's no history in this tree.

As the crtc/output-based mode selection code uses ddc, the ddc and i2c
modules have been merged into the server. Attempts to load them are safely
ignored now.
This commit is contained in:
Keith Packard 2007-02-15 20:36:20 -08:00
parent 37fe4c49dc
commit d4eb4d0650
22 changed files with 5404 additions and 13 deletions

View File

@ -1905,6 +1905,7 @@ hw/xfree86/fbdevhw/Makefile
hw/xfree86/i2c/Makefile
hw/xfree86/int10/Makefile
hw/xfree86/loader/Makefile
hw/xfree86/modes/Makefile
hw/xfree86/os-support/Makefile
hw/xfree86/os-support/bsd/Makefile
hw/xfree86/os-support/bus/Makefile

View File

@ -12,7 +12,7 @@ DOC_SUBDIR = doc
SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support parser rac \
ramdac shadowfb vbe vgahw xaa xf1bpp xf4bpp xf8_16bpp \
xf8_32bpp loader scanpci dixmods exa \
xf8_32bpp loader scanpci dixmods exa modes \
$(DRI_SUBDIR) $(XF86UTILS_SUBDIR) $(DOC_SUBDIR)
DIST_SUBDIRS = common ddc dummylib i2c x86emu int10 fbdevhw os-support \
@ -47,6 +47,9 @@ XORG_LIBS = \
rac/librac.a \
parser/libxf86config.a \
dixmods/libdixmods.la \
modes/libxf86modes.a \
ddc/libddc.a \
i2c/libi2c.a \
@XORG_LIBS@
Xorg_DEPENDENCIES = \

View File

@ -1,11 +1,10 @@
sdk_HEADERS = edid.h vdif.h xf86DDC.h
module_LTLIBRARIES = libddc.la
noinst_LIBRARIES = libddc.a
libddc_la_LDFLAGS = -avoid-version
libddc_la_SOURCES = xf86DDC.c edid.c interpret_edid.c print_edid.c \
libddc_a_SOURCES = xf86DDC.c edid.c interpret_edid.c print_edid.c \
interpret_vdif.c print_vdif.c ddcProperty.c \
edid_modes.c
edid_modes.c
INCLUDES = $(XORG_INCS) -I$(srcdir)/../i2c

View File

@ -31,6 +31,7 @@
#include "property.h"
#include "propertyst.h"
#include "xf86DDC.h"
#include "xf86_ansic.h"
#define EDID1_ATOM_NAME "XFree86_DDC_EDID1_RAWDATA"
#define EDID2_ATOM_NAME "XFree86_DDC_EDID2_RAWDATA"

View File

@ -15,6 +15,8 @@
static const OptionInfoRec *DDCAvailableOptions(void *unused);
#if DDC_MODULE
static MODULESETUPPROTO(ddcSetup);
static XF86ModuleVersionInfo ddcVersRec =
@ -57,6 +59,8 @@ ddcSetup(pointer module, pointer opts, int *errmaj, int *errmin)
return (pointer)1;
}
#endif
#define RETRIES 4
static unsigned char *EDIDRead_DDC1(

View File

@ -1,4 +1,4 @@
module_LTLIBRARIES = libi2c.la
module_LIBRARIES = libi2c.a
multimediadir = $(moduledir)/multimedia
multimedia_LTLIBRARIES = \
@ -10,8 +10,7 @@ multimedia_LTLIBRARIES = \
tda9885_drv.la \
uda1380_drv.la
libi2c_la_LDFLAGS = -avoid-version
libi2c_la_SOURCES = xf86i2c.c xf86i2cmodule.c
libi2c_a_SOURCES = xf86i2c.c
INCLUDES = $(XORG_INCS)

View File

@ -2,7 +2,7 @@ noinst_LIBRARIES = libloader.a
INCLUDES = $(XORG_INCS) -I$(srcdir)/../parser -I$(srcdir)/../dixmods/extmod \
-I$(srcdir)/../vbe -I$(top_srcdir)/miext/cw -I$(srcdir)/../int10 \
-I$(srcdir)/../ddc -I$(srcdir)/../i2c
-I$(srcdir)/../ddc -I$(srcdir)/../i2c -I$(srcdir)/../modes
#AM_LDFLAGS = -r
AM_CFLAGS = -DIN_LOADER $(DIX_CFLAGS) $(XORG_CFLAGS)

View File

@ -768,7 +768,7 @@ LoadSubModule(ModuleDescPtr parent, const char *module,
submod = doLoadModule(module, NULL, subdirlist, patternlist, options,
modreq, errmaj, errmin, LD_FLAG_GLOBAL);
if (submod) {
if (submod && submod != (ModuleDescPtr) 1) {
parent->child = AddSibling(parent->child, submod);
submod->parent = parent;
}
@ -799,7 +799,7 @@ LoadSubModuleLocal(ModuleDescPtr parent, const char *module,
submod = doLoadModule(module, NULL, subdirlist, patternlist, options,
modreq, errmaj, errmin, 0);
if (submod) {
if (submod && submod != (ModuleDescPtr) 1) {
parent->child = AddSibling(parent->child, submod);
submod->parent = parent;
}
@ -838,6 +838,11 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
return ret;
}
static const char *compiled_in_modules[] = {
"ddc",
"i2c",
NULL
};
static ModuleDescPtr
doLoadModule(const char *module, const char *path, const char **subdirlist,
@ -856,9 +861,17 @@ doLoadModule(const char *module, const char *path, const char **subdirlist,
PatternPtr patterns = NULL;
int noncanonical = 0;
char *m = NULL;
char **cim;
xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module);
for (cim = compiled_in_modules; *cim; cim++)
if (!strcmp (module, *cim))
{
xf86MsgVerb(X_INFO, 3, "Module alread ybuilt-in");
return (ModuleDescPtr) 1;
}
patterns = InitPatterns(patternlist);
name = LoaderGetCanonicalName(module, patterns);
noncanonical = (name && strcmp(module, name) != 0);
@ -1108,6 +1121,9 @@ UnloadDriver(ModuleDescPtr mod)
static void
UnloadModuleOrDriver(ModuleDescPtr mod)
{
if (mod == (ModuleDescPtr) 1)
return;
if (mod == NULL || mod->name == NULL)
return;
@ -1156,6 +1172,8 @@ FreeModuleDesc(ModuleDescPtr head)
{
ModuleDescPtr sibs, prev;
if (head == (ModuleDescPtr) 1)
return;
/*
* only free it if it's not marked as in use. In use means that it may
* be unloaded someday, and UnloadModule or UnloadDriver will free it
@ -1338,7 +1356,7 @@ LoaderGetCanonicalName(const char *modname, PatternPtr patterns)
unsigned long
LoaderGetModuleVersion(ModuleDescPtr mod)
{
if (!mod || !mod->VersionInfo)
if (!mod || mod == (ModuleDescPtr) 1 || !mod->VersionInfo)
return 0;
return MODULE_VERSION_NUMERIC(mod->VersionInfo->majorversion,

View File

@ -89,6 +89,13 @@
#include "xf86sbusBus.h"
#endif
#include "compiler.h"
#include "xf86Crtc.h"
#include "xf86Modes.h"
#ifdef RANDR
#include "xf86RandR12.h"
#endif
#include "xf86DDC.h"
#include "edid.h"
#ifndef HAS_GLIBC_SIGSETJMP
#if defined(setjmp) && defined(__GNU_LIBRARY__) && \
@ -1161,4 +1168,85 @@ _X_HIDDEN void *xfree86LookupTab[] = {
/* Pci.c */
SYMVAR(pciNumBuses)
/* modes */
SYMFUNC(xf86CrtcConfigInit)
SYMFUNC(xf86CrtcConfigPrivateIndex)
SYMFUNC(xf86CrtcCreate)
SYMFUNC(xf86CrtcDestroy)
SYMFUNC(xf86CrtcInUse)
SYMFUNC(xf86CrtcRotate)
SYMFUNC(xf86CrtcSetMode)
SYMFUNC(xf86CrtcSetSizeRange)
SYMFUNC(xf86CVTMode)
SYMFUNC(xf86DisableUnusedFunctions)
SYMFUNC(xf86DPMSSet)
SYMFUNC(xf86DuplicateMode)
SYMFUNC(xf86DuplicateModes)
SYMFUNC(xf86GetDefaultModes)
SYMFUNC(xf86GetMonitorModes)
SYMFUNC(xf86InitialConfiguration)
SYMFUNC(xf86ModeHSync)
SYMFUNC(xf86ModesAdd)
SYMFUNC(xf86ModesEqual)
SYMFUNC(xf86ModeVRefresh)
SYMFUNC(xf86OutputCreate)
SYMFUNC(xf86OutputDestroy)
SYMFUNC(xf86OutputGetEDID)
SYMFUNC(xf86OutputGetEDIDModes)
SYMFUNC(xf86OutputRename)
SYMFUNC(xf86OutputSetEDID)
SYMFUNC(xf86PrintModeline)
SYMFUNC(xf86ProbeOutputModes)
SYMFUNC(xf86PruneInvalidModes)
SYMFUNC(xf86SetModeCrtc)
SYMFUNC(xf86SetModeDefaultName)
SYMFUNC(xf86SetScrnInfoModes)
SYMFUNC(xf86ValidateModesClocks)
SYMFUNC(xf86ValidateModesFlags)
SYMFUNC(xf86ValidateModesSize)
SYMFUNC(xf86ValidateModesSync)
SYMFUNC(xf86ValidateModesUserConfig)
SYMFUNC(xf86DiDGAInit)
SYMFUNC(xf86DiDGAReInit)
SYMFUNC(xf86DDCGetModes)
SYMFUNC(xf86SaveScreen)
#ifdef RANDR
SYMFUNC(xf86RandR12CreateScreenResources)
SYMFUNC(xf86RandR12GetOriginalVirtualSize)
SYMFUNC(xf86RandR12GetRotation)
SYMFUNC(xf86RandR12Init)
SYMFUNC(xf86RandR12PreInit)
SYMFUNC(xf86RandR12SetConfig)
SYMFUNC(xf86RandR12SetRotations)
#endif
SYMFUNC(xf86DoEDID_DDC1)
SYMFUNC(xf86DoEDID_DDC2)
SYMFUNC(xf86InterpretEDID)
SYMFUNC(xf86PrintEDID)
SYMFUNC(xf86InterpretVdif)
SYMFUNC(xf86print_vdif)
SYMFUNC(xf86DDCMonitorSet)
SYMFUNC(xf86SetDDCproperties)
SYMFUNC(xf86CreateI2CBusRec)
SYMFUNC(xf86CreateI2CDevRec)
SYMFUNC(xf86DestroyI2CBusRec)
SYMFUNC(xf86DestroyI2CDevRec)
SYMFUNC(xf86I2CBusInit)
SYMFUNC(xf86I2CDevInit)
SYMFUNC(xf86I2CFindBus)
SYMFUNC(xf86I2CFindDev)
SYMFUNC(xf86I2CGetScreenBuses)
SYMFUNC(xf86I2CProbeAddress)
SYMFUNC(xf86I2CReadByte)
SYMFUNC(xf86I2CReadBytes)
SYMFUNC(xf86I2CReadStatus)
SYMFUNC(xf86I2CReadWord)
SYMFUNC(xf86I2CWriteByte)
SYMFUNC(xf86I2CWriteBytes)
SYMFUNC(xf86I2CWriteRead)
SYMFUNC(xf86I2CWriteVec)
SYMFUNC(xf86I2CWriteWord)
};

View File

@ -0,0 +1,27 @@
noinst_LIBRARIES = libxf86modes.a
libxf86modes_a_SOURCES = \
xf86Crtc.c \
xf86Crtc.h \
xf86cvt.c \
xf86DiDGA.c \
xf86EdidModes.c \
xf86Modes.c \
xf86Modes.h \
xf86RandR12.c \
xf86RandR12.h \
xf86Rename.h \
xf86Rotate.c
INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \
-I$(srcdir)/../loader -I$(srcdir)/../rac -I$(srcdir)/../parser \
-I$(srcdir)/../scanpci -I$(srcdir)/../vbe -I$(srcdir)/../int10 \
-I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod
sdk_HEADERS = \
xf86Crtc.h \
xf86Modes.h \
xf86RandR12.h \
xf86Rename.h
AM_CFLAGS = $(XORG_CFLAGS)

1587
hw/xfree86/modes/xf86Crtc.c Normal file

File diff suppressed because it is too large Load Diff

555
hw/xfree86/modes/xf86Crtc.h Normal file
View File

@ -0,0 +1,555 @@
/*
* 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.
*/
#ifndef _XF86CRTC_H_
#define _XF86CRTC_H_
#include <edid.h>
#include "randrstr.h"
#if XF86_MODES_RENAME
#include "xf86Rename.h"
#endif
#include "xf86Modes.h"
#include "xf86Parser.h"
#include "damage.h"
/* Compat definitions for older X Servers. */
#ifndef M_T_PREFERRED
#define M_T_PREFERRED 0x08
#endif
#ifndef M_T_DRIVER
#define M_T_DRIVER 0x40
#endif
typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
typedef enum _xf86OutputStatus {
XF86OutputStatusConnected,
XF86OutputStatusDisconnected,
XF86OutputStatusUnknown,
} xf86OutputStatus;
typedef struct _xf86CrtcFuncs {
/**
* Turns the crtc on/off, or sets intermediate power levels if available.
*
* Unsupported intermediate modes drop to the lower power setting. If the
* mode is DPMSModeOff, the crtc must be disabled sufficiently for it to
* be safe to call mode_set.
*/
void
(*dpms)(xf86CrtcPtr crtc,
int mode);
/**
* Saves the crtc's state for restoration on VT switch.
*/
void
(*save)(xf86CrtcPtr crtc);
/**
* Restore's the crtc's state at VT switch.
*/
void
(*restore)(xf86CrtcPtr crtc);
/**
* Lock CRTC prior to mode setting, mostly for DRI.
* Returns whether unlock is needed
*/
Bool
(*lock) (xf86CrtcPtr crtc);
/**
* Unlock CRTC after mode setting, mostly for DRI
*/
void
(*unlock) (xf86CrtcPtr crtc);
/**
* Callback to adjust the mode to be set in the CRTC.
*
* This allows a CRTC to adjust the clock or even the entire set of
* timings, which is used for panels with fixed timings or for
* buses with clock limitations.
*/
Bool
(*mode_fixup)(xf86CrtcPtr crtc,
DisplayModePtr mode,
DisplayModePtr adjusted_mode);
/**
* Callback for setting up a video mode after fixups have been made.
*/
void
(*mode_set)(xf86CrtcPtr crtc,
DisplayModePtr mode,
DisplayModePtr adjusted_mode,
int x, int y);
/* Set the color ramps for the CRTC to the given values. */
void
(*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
int size);
/**
* Create shadow pixmap for rotation support
*/
PixmapPtr
(*shadow_create) (xf86CrtcPtr crtc, int width, int height);
/**
* Destroy shadow pixmap
*/
void
(*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap);
/**
* Clean up driver-specific bits of the crtc
*/
void
(*destroy) (xf86CrtcPtr crtc);
} xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
struct _xf86Crtc {
/**
* Associated ScrnInfo
*/
ScrnInfoPtr scrn;
/**
* Active state of this CRTC
*
* Set when this CRTC is driving one or more outputs
*/
Bool enabled;
/** Track whether cursor is within CRTC range */
Bool cursorInRange;
/** Track state of cursor associated with this CRTC */
Bool cursorShown;
/**
* Active mode
*
* This reflects the mode as set in the CRTC currently
* It will be cleared when the VT is not active or
* during server startup
*/
DisplayModeRec mode;
Rotation rotation;
PixmapPtr rotatedPixmap;
/**
* Position on screen
*
* Locates this CRTC within the frame buffer
*/
int x, y;
/**
* Desired mode
*
* This is set to the requested mode, independent of
* whether the VT is active. In particular, it receives
* the startup configured mode and saves the active mode
* on VT switch.
*/
DisplayModeRec desiredMode;
Rotation desiredRotation;
int desiredX, desiredY;
/** crtc-specific functions */
const xf86CrtcFuncsRec *funcs;
/**
* Driver private
*
* Holds driver-private information
*/
void *driver_private;
#ifdef RANDR_12_INTERFACE
/**
* RandR crtc
*
* When RandR 1.2 is available, this
* points at the associated crtc object
*/
RRCrtcPtr randr_crtc;
#else
void *randr_crtc;
#endif
};
typedef struct _xf86OutputFuncs {
/**
* Called to allow the output a chance to create properties after the
* RandR objects have been created.
*/
void
(*create_resources)(xf86OutputPtr output);
/**
* Turns the output on/off, or sets intermediate power levels if available.
*
* Unsupported intermediate modes drop to the lower power setting. If the
* mode is DPMSModeOff, the output must be disabled, as the DPLL may be
* disabled afterwards.
*/
void
(*dpms)(xf86OutputPtr output,
int mode);
/**
* Saves the output's state for restoration on VT switch.
*/
void
(*save)(xf86OutputPtr output);
/**
* Restore's the output's state at VT switch.
*/
void
(*restore)(xf86OutputPtr output);
/**
* Callback for testing a video mode for a given output.
*
* This function should only check for cases where a mode can't be supported
* on the output specifically, and not represent generic CRTC limitations.
*
* \return MODE_OK if the mode is valid, or another MODE_* otherwise.
*/
int
(*mode_valid)(xf86OutputPtr output,
DisplayModePtr pMode);
/**
* Callback to adjust the mode to be set in the CRTC.
*
* This allows an output to adjust the clock or even the entire set of
* timings, which is used for panels with fixed timings or for
* buses with clock limitations.
*/
Bool
(*mode_fixup)(xf86OutputPtr output,
DisplayModePtr mode,
DisplayModePtr adjusted_mode);
/**
* Callback for setting up a video mode after fixups have been made.
*
* This is only called while the output is disabled. The dpms callback
* must be all that's necessary for the output, to turn the output on
* after this function is called.
*/
void
(*mode_set)(xf86OutputPtr output,
DisplayModePtr mode,
DisplayModePtr adjusted_mode);
/**
* Probe for a connected output, and return detect_status.
*/
xf86OutputStatus
(*detect)(xf86OutputPtr output);
/**
* Query the device for the modes it provides.
*
* This function may also update MonInfo, mm_width, and mm_height.
*
* \return singly-linked list of modes or NULL if no modes found.
*/
DisplayModePtr
(*get_modes)(xf86OutputPtr output);
#ifdef RANDR_12_INTERFACE
/**
* Callback when an output's property has changed.
*/
Bool
(*set_property)(xf86OutputPtr output,
Atom property,
RRPropertyValuePtr value);
#endif
/**
* Clean up driver-specific bits of the output
*/
void
(*destroy) (xf86OutputPtr output);
} xf86OutputFuncsRec, *xf86OutputFuncsPtr;
struct _xf86Output {
/**
* Associated ScrnInfo
*/
ScrnInfoPtr scrn;
/**
* Currently connected crtc (if any)
*
* If this output is not in use, this field will be NULL.
*/
xf86CrtcPtr crtc;
/**
* Possible CRTCs for this output as a mask of crtc indices
*/
CARD32 possible_crtcs;
/**
* Possible outputs to share the same CRTC as a mask of output indices
*/
CARD32 possible_clones;
/**
* Whether this output can support interlaced modes
*/
Bool interlaceAllowed;
/**
* Whether this output can support double scan modes
*/
Bool doubleScanAllowed;
/**
* List of available modes on this output.
*
* This should be the list from get_modes(), plus perhaps additional
* compatible modes added later.
*/
DisplayModePtr probed_modes;
/**
* Options parsed from the related monitor section
*/
OptionInfoPtr options;
/**
* Configured monitor section
*/
XF86ConfMonitorPtr conf_monitor;
/**
* Desired initial position
*/
int initial_x, initial_y;
/**
* Current connection status
*
* This indicates whether a monitor is known to be connected
* to this output or not, or whether there is no way to tell
*/
xf86OutputStatus status;
/** EDID monitor information */
xf86MonPtr MonInfo;
/** subpixel order */
int subpixel_order;
/** Physical size of the currently attached output device. */
int mm_width, mm_height;
/** Output name */
char *name;
/** output-specific functions */
const xf86OutputFuncsRec *funcs;
/** driver private information */
void *driver_private;
#ifdef RANDR_12_INTERFACE
/**
* RandR 1.2 output structure.
*
* When RandR 1.2 is available, this points at the associated
* RandR output structure and is created when this output is created
*/
RROutputPtr randr_output;
#else
void *randr_output;
#endif
};
typedef struct _xf86CrtcConfig {
int num_output;
xf86OutputPtr *output;
/**
* compat_output is used whenever we deal
* with legacy code that only understands a single
* output. pScrn->modes will be loaded from this output,
* adjust frame will whack this output, etc.
*/
int compat_output;
int num_crtc;
xf86CrtcPtr *crtc;
int minWidth, minHeight;
int maxWidth, maxHeight;
/* For crtc-based rotation */
DamagePtr rotationDamage;
/* DGA */
unsigned int dga_flags;
unsigned long dga_address;
DGAModePtr dga_modes;
int dga_nmode;
int dga_width, dga_height, dga_stride;
DisplayModePtr dga_save_mode;
} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
extern int xf86CrtcConfigPrivateIndex;
#define XF86_CRTC_CONFIG_PTR(p) ((xf86CrtcConfigPtr) ((p)->privates[xf86CrtcConfigPrivateIndex].ptr))
/*
* Initialize xf86CrtcConfig structure
*/
void
xf86CrtcConfigInit (ScrnInfoPtr scrn);
void
xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
int minWidth, int minHeight,
int maxWidth, int maxHeight);
/*
* Crtc functions
*/
xf86CrtcPtr
xf86CrtcCreate (ScrnInfoPtr scrn,
const xf86CrtcFuncsRec *funcs);
void
xf86CrtcDestroy (xf86CrtcPtr crtc);
/**
* Allocate a crtc for the specified output
*
* Find a currently unused CRTC which is suitable for
* the specified output
*/
xf86CrtcPtr
xf86AllocCrtc (xf86OutputPtr output);
/**
* Free a crtc
*
* Mark the crtc as unused by any outputs
*/
void
xf86FreeCrtc (xf86CrtcPtr crtc);
/**
* Sets the given video mode on the given crtc
*/
Bool
xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
int x, int y);
/*
* Assign crtc rotation during mode set
*/
Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
/**
* Return whether any output is assigned to the crtc
*/
Bool
xf86CrtcInUse (xf86CrtcPtr crtc);
/*
* Output functions
*/
xf86OutputPtr
xf86OutputCreate (ScrnInfoPtr scrn,
const xf86OutputFuncsRec *funcs,
const char *name);
Bool
xf86OutputRename (xf86OutputPtr output, const char *name);
void
xf86OutputDestroy (xf86OutputPtr output);
void
xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY);
void
xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
Bool
xf86InitialConfiguration (ScrnInfoPtr pScrn);
void
xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
Bool
xf86SaveScreen(ScreenPtr pScreen, int mode);
void
xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
/**
* Set the EDID information for the specified output
*/
void
xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
/**
* Return the list of modes supported by the EDID information
* stored in 'output'
*/
DisplayModePtr
xf86OutputGetEDIDModes (xf86OutputPtr output);
xf86MonPtr
xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
/**
* Initialize dga for this screen
*/
Bool
xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address);
/**
* Re-initialize dga for this screen (as when the set of modes changes)
*/
Bool
xf86DiDGAReInit (ScreenPtr pScreen);
#endif /* _XF86CRTC_H_ */

View File

@ -0,0 +1,280 @@
/*
* 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>
#endif
#include "xf86.h"
#include "xf86DDC.h"
#include "xf86_OSproc.h"
#include "dgaproc.h"
#include "xf86Crtc.h"
#include "xf86Modes.h"
#include "gcstruct.h"
static Bool
xf86_dga_get_modes (ScreenPtr pScreen)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
DGAModePtr modes, mode;
DisplayModePtr display_mode;
int bpp = scrn->bitsPerPixel >> 3;
int num;
num = 0;
display_mode = scrn->modes;
while (display_mode)
{
num++;
display_mode = display_mode->next;
if (display_mode == scrn->modes)
break;
}
if (!num)
return FALSE;
modes = xalloc(num * sizeof(DGAModeRec));
if (!modes)
return FALSE;
num = 0;
display_mode = scrn->modes;
while (display_mode)
{
mode = modes + num++;
mode->mode = display_mode;
mode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
if (display_mode->Flags & V_DBLSCAN)
mode->flags |= DGA_DOUBLESCAN;
if (display_mode->Flags & V_INTERLACE)
mode->flags |= DGA_INTERLACED;
mode->byteOrder = scrn->imageByteOrder;
mode->depth = scrn->depth;
mode->bitsPerPixel = scrn->bitsPerPixel;
mode->red_mask = scrn->mask.red;
mode->green_mask = scrn->mask.green;
mode->blue_mask = scrn->mask.blue;
mode->visualClass = (bpp == 1) ? PseudoColor : TrueColor;
mode->viewportWidth = display_mode->HDisplay;
mode->viewportHeight = display_mode->VDisplay;
mode->xViewportStep = (bpp == 3) ? 2 : 1;
mode->yViewportStep = 1;
mode->viewportFlags = DGA_FLIP_RETRACE;
mode->offset = 0;
mode->address = (unsigned char *) xf86_config->dga_address;
mode->bytesPerScanline = xf86_config->dga_stride;
mode->imageWidth = xf86_config->dga_width;
mode->imageHeight = xf86_config->dga_height;
mode->pixmapWidth = mode->imageWidth;
mode->pixmapHeight = mode->imageHeight;
mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
display_mode = display_mode->next;
if (display_mode == scrn->modes)
break;
}
if (xf86_config->dga_modes)
xfree (xf86_config->dga_modes);
xf86_config->dga_nmode = num;
xf86_config->dga_modes = modes;
return TRUE;
}
static Bool
xf86_dga_set_mode(ScrnInfoPtr scrn, DGAModePtr display_mode)
{
ScreenPtr pScreen = scrn->pScreen;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
if (!display_mode)
{
if (xf86_config->dga_save_mode)
{
xf86SwitchMode(pScreen, xf86_config->dga_save_mode);
xf86_config->dga_save_mode = NULL;
}
}
else
{
if (!xf86_config->dga_save_mode)
{
xf86_config->dga_save_mode = scrn->currentMode;
xf86SwitchMode(pScreen, display_mode->mode);
}
}
return TRUE;
}
static int
xf86_dga_get_viewport(ScrnInfoPtr scrn)
{
return 0;
}
static void
xf86_dga_set_viewport(ScrnInfoPtr scrn, int x, int y, int flags)
{
scrn->AdjustFrame(scrn->pScreen->myNum, x, y, flags);
}
static Bool
xf86_dga_get_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr *ppDrawable, GCPtr *ppGC)
{
ScreenPtr pScreen = scrn->pScreen;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
PixmapPtr pPixmap;
GCPtr pGC;
pPixmap = GetScratchPixmapHeader (pScreen, xf86_config->dga_width, xf86_config->dga_height,
scrn->depth, scrn->bitsPerPixel, xf86_config->dga_stride,
(char *) scrn->memPhysBase + scrn->fbOffset);
if (!pPixmap)
return FALSE;
pGC = GetScratchGC (scrn->depth, pScreen);
if (!pGC)
{
FreeScratchPixmapHeader (pPixmap);
return FALSE;
}
*ppDrawable = &pPixmap->drawable;
*ppGC = pGC;
return TRUE;
}
static void
xf86_dga_release_drawable_and_gc (ScrnInfoPtr scrn, DrawablePtr pDrawable, GCPtr pGC)
{
FreeScratchGC (pGC);
FreeScratchPixmapHeader ((PixmapPtr) pDrawable);
}
static void
xf86_dga_fill_rect(ScrnInfoPtr scrn, int x, int y, int w, int h, unsigned long color)
{
GCPtr pGC;
DrawablePtr pDrawable;
XID vals[1];
xRectangle r;
if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
return;
vals[0] = color;
ChangeGC (pGC, GCForeground, vals);
ValidateGC (pDrawable, pGC);
r.x = x;
r.y = y;
r.width = w;
r.height = h;
pGC->ops->PolyFillRect (pDrawable, pGC, 1, &r);
xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
}
static void
xf86_dga_sync(ScrnInfoPtr scrn)
{
ScreenPtr pScreen = scrn->pScreen;
WindowPtr pRoot = WindowTable [pScreen->myNum];
char buffer[4];
pScreen->GetImage (&pRoot->drawable, 0, 0, 1, 1, ZPixmap, ~0L, buffer);
}
static void
xf86_dga_blit_rect(ScrnInfoPtr scrn, int srcx, int srcy, int w, int h, int dstx, int dsty)
{
DrawablePtr pDrawable;
GCPtr pGC;
if (!xf86_dga_get_drawable_and_gc (scrn, &pDrawable, &pGC))
return;
ValidateGC (pDrawable, pGC);
pGC->ops->CopyArea (pDrawable, pDrawable, pGC, srcx, srcy, w, h, dstx, dsty);
xf86_dga_release_drawable_and_gc (scrn, pDrawable, pGC);
}
static Bool
xf86_dga_open_framebuffer(ScrnInfoPtr scrn,
char **name,
unsigned char **mem, int *size, int *offset, int *flags)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
*size = xf86_config->dga_stride * xf86_config->dga_height;
*mem = (unsigned char *) (xf86_config->dga_address);
*offset = 0;
*flags = DGA_NEED_ROOT;
return TRUE;
}
static void
xf86_dga_close_framebuffer(ScrnInfoPtr scrn)
{
}
static DGAFunctionRec xf86_dga_funcs = {
xf86_dga_open_framebuffer,
xf86_dga_close_framebuffer,
xf86_dga_set_mode,
xf86_dga_set_viewport,
xf86_dga_get_viewport,
xf86_dga_sync,
xf86_dga_fill_rect,
xf86_dga_blit_rect,
NULL
};
Bool
xf86DiDGAReInit (ScreenPtr pScreen)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
if (!xf86_dga_get_modes (pScreen))
return FALSE;
return DGAReInitModes (pScreen, xf86_config->dga_modes, xf86_config->dga_nmode);
}
Bool
xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address)
{
ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
xf86_config->dga_flags = 0;
xf86_config->dga_address = dga_address;
xf86_config->dga_width = scrn->virtualX;
xf86_config->dga_height = scrn->virtualY;
xf86_config->dga_stride = scrn->displayWidth * scrn->bitsPerPixel >> 3;
if (!xf86_dga_get_modes (pScreen))
return FALSE;
return DGAInit(pScreen, &xf86_dga_funcs, xf86_config->dga_modes, xf86_config->dga_nmode);
}

View File

@ -0,0 +1,339 @@
/*
* Copyright 2006 Luc Verhaegen.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sub license,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/**
* @file This is a copy of edid_modes.c from the X Server, for compatibility
* with old X Servers.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf86.h"
#include "xf86DDC.h"
#include <X11/Xatom.h>
#include "property.h"
#include "propertyst.h"
#include "xf86DDC.h"
#include "xf86Crtc.h"
#include <string.h>
#include <math.h>
/*
* Quirks to work around broken EDID data from various monitors.
*/
typedef enum {
DDC_QUIRK_NONE = 0,
/* Force detailed sync polarity to -h +v */
DDC_QUIRK_DT_SYNC_HM_VP = 1 << 0,
/* First detailed mode is bogus, prefer largest mode at 60hz */
DDC_QUIRK_PREFER_LARGE_60 = 1 << 1,
/* 135MHz clock is too high, drop a bit */
DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 2
} ddc_quirk_t;
static Bool quirk_dt_sync_hm_vp (int scrnIndex, xf86MonPtr DDC)
{
/* Belinea 1924S1W */
if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
DDC->vendor.prod_id == 1932)
return TRUE;
/* Belinea 10 20 30W */
if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
DDC->vendor.prod_id == 2007)
return TRUE;
/* ViewSonic VX2025wm (bug #9941) */
if (memcmp (DDC->vendor.name, "VSC", 4) == 0 &&
DDC->vendor.prod_id == 58653)
return TRUE;
return FALSE;
}
static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
{
/* Belinea 10 15 55 */
if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
DDC->vendor.prod_id == 1516)
return TRUE;
return FALSE;
}
static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
{
/* Envision Peripherals, Inc. EN-7100e. See bug #9550. */
if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
DDC->vendor.prod_id == 59264)
return TRUE;
return FALSE;
}
typedef struct {
Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
ddc_quirk_t quirk;
char *description;
} ddc_quirk_map_t;
static const ddc_quirk_map_t ddc_quirks[] = {
{
quirk_dt_sync_hm_vp, DDC_QUIRK_DT_SYNC_HM_VP,
"Set detailed timing sync polarity to -h +v"
},
{
quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60,
"Detailed timing is not preferred, use largest mode at 60Hz"
},
{
quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH,
"Recommended 135MHz pixel clock is too high"
},
{
NULL, DDC_QUIRK_NONE,
"No known quirks"
},
};
/*
* TODO:
* - for those with access to the VESA DMT standard; review please.
*/
#define MODEPREFIX(name) NULL, NULL, name, 0,M_T_DRIVER
#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
static DisplayModeRec DDCEstablishedModes[17] = {
{ MODEPREFIX("800x600"), 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
{ MODEPREFIX("800x600"), 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
{ MODEPREFIX("640x480"), 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
{ MODEPREFIX("640x480"), 31500, 640, 664, 704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
{ MODEPREFIX("640x480"), 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
{ MODEPREFIX("640x480"), 25200, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
{ MODEPREFIX("720x400"), 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
{ MODEPREFIX("720x400"), 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
{ MODEPREFIX("1280x1024"), 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
{ MODEPREFIX("1024x768"), 78800, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
{ MODEPREFIX("1024x768"), 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
{ MODEPREFIX("1024x768"), 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
{ MODEPREFIX("1024x768"), 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 776, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
{ MODEPREFIX("832x624"), 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
{ MODEPREFIX("800x600"), 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
{ MODEPREFIX("800x600"), 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
{ MODEPREFIX("1152x864"), 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
};
static DisplayModePtr
DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
ddc_quirk_t quirks)
{
DisplayModePtr Modes = NULL, Mode = NULL;
CARD32 bits = (timing->t1) | (timing->t2 << 8) |
((timing->t_manu & 0x80) << 9);
int i;
for (i = 0; i < 17; i++) {
if (bits & (0x01 << i)) {
Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
Modes = xf86ModesAdd(Modes, Mode);
}
}
return Modes;
}
/*
*
*/
static DisplayModePtr
DDCModesFromStandardTiming(int scrnIndex, struct std_timings *timing,
ddc_quirk_t quirks)
{
DisplayModePtr Modes = NULL, Mode = NULL;
int i;
for (i = 0; i < STD_TIMINGS; i++) {
if (timing[i].hsize && timing[i].vsize && timing[i].refresh) {
Mode = xf86CVTMode(timing[i].hsize, timing[i].vsize,
timing[i].refresh, FALSE, FALSE);
Mode->type = M_T_DRIVER;
Modes = xf86ModesAdd(Modes, Mode);
}
}
return Modes;
}
/*
*
*/
static DisplayModePtr
DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
int preferred, ddc_quirk_t quirks)
{
DisplayModePtr Mode;
/* We don't do stereo */
if (timing->stereo) {
xf86DrvMsg(scrnIndex, X_INFO,
"%s: Ignoring: We don't handle stereo.\n", __func__);
return NULL;
}
/* We only do seperate sync currently */
if (timing->sync != 0x03) {
xf86DrvMsg(scrnIndex, X_INFO,
"%s: %dx%d Warning: We only handle seperate"
" sync.\n", __func__, timing->h_active, timing->v_active);
}
Mode = xnfalloc(sizeof(DisplayModeRec));
memset(Mode, 0, sizeof(DisplayModeRec));
Mode->type = M_T_DRIVER;
if (preferred)
Mode->type |= M_T_PREFERRED;
if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
timing->clock == 135000000 )
Mode->Clock = 108880;
else
Mode->Clock = timing->clock / 1000.0;
Mode->HDisplay = timing->h_active;
Mode->HSyncStart = timing->h_active + timing->h_sync_off;
Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
Mode->HTotal = timing->h_active + timing->h_blanking;
Mode->VDisplay = timing->v_active;
Mode->VSyncStart = timing->v_active + timing->v_sync_off;
Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
Mode->VTotal = timing->v_active + timing->v_blanking;
xf86SetModeDefaultName(Mode);
/* We ignore h/v_size and h/v_border for now. */
if (timing->interlaced)
Mode->Flags |= V_INTERLACE;
if (quirks & DDC_QUIRK_DT_SYNC_HM_VP)
Mode->Flags |= V_NHSYNC | V_PVSYNC;
else
{
if (timing->misc & 0x02)
Mode->Flags |= V_PHSYNC;
else
Mode->Flags |= V_NHSYNC;
if (timing->misc & 0x01)
Mode->Flags |= V_PVSYNC;
else
Mode->Flags |= V_NVSYNC;
}
return Mode;
}
DisplayModePtr
xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
{
int preferred, i;
DisplayModePtr Modes = NULL, Mode;
ddc_quirk_t quirks;
xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
DDC->vendor.name, DDC->vendor.prod_id);
quirks = DDC_QUIRK_NONE;
for (i = 0; ddc_quirks[i].detect; i++)
if (ddc_quirks[i].detect (scrnIndex, DDC))
{
xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
ddc_quirks[i].description);
quirks |= ddc_quirks[i].quirk;
}
preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
if (quirks & DDC_QUIRK_PREFER_LARGE_60)
preferred = 0;
for (i = 0; i < DET_TIMINGS; i++) {
struct detailed_monitor_section *det_mon = &DDC->det_mon[i];
switch (det_mon->type) {
case DT:
Mode = DDCModeFromDetailedTiming(scrnIndex,
&det_mon->section.d_timings,
preferred,
quirks);
preferred = 0;
Modes = xf86ModesAdd(Modes, Mode);
break;
case DS_STD_TIMINGS:
Mode = DDCModesFromStandardTiming(scrnIndex,
det_mon->section.std_t,
quirks);
Modes = xf86ModesAdd(Modes, Mode);
break;
default:
break;
}
}
/* Add established timings */
Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
Modes = xf86ModesAdd(Modes, Mode);
/* Add standard timings */
Mode = DDCModesFromStandardTiming(scrnIndex, DDC->timings2, quirks);
Modes = xf86ModesAdd(Modes, Mode);
if (quirks & DDC_QUIRK_PREFER_LARGE_60)
{
DisplayModePtr best = Modes;
for (Mode = Modes; Mode; Mode = Mode->next)
{
if (Mode == best) continue;
if (Mode->HDisplay * Mode->VDisplay > best->HDisplay * best->VDisplay)
{
best = Mode;
continue;
}
if (Mode->HDisplay * Mode->VDisplay == best->HDisplay * best->VDisplay)
{
double mode_refresh = xf86ModeVRefresh (Mode);
double best_refresh = xf86ModeVRefresh (best);
double mode_dist = fabs(mode_refresh - 60.0);
double best_dist = fabs(best_refresh - 60.0);
if (mode_dist < best_dist)
{
best = Mode;
continue;
}
}
}
if (best)
best->type |= M_T_PREFERRED;
}
return Modes;
}

View File

@ -0,0 +1,635 @@
/* -*- c-basic-offset: 4 -*- */
/* $XdotOrg: xserver/xorg/hw/xfree86/common/xf86Mode.c,v 1.10 2006/03/07 16:00:57 libv Exp $ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Mode.c,v 1.69 2003/10/08 14:58:28 dawes Exp $ */
/*
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "xf86.h"
#include "xf86Modes.h"
#include "xf86Priv.h"
extern XF86ConfigPtr xf86configptr;
/**
* @file this file contains symbols from xf86Mode.c and friends that are static
* there but we still want to use. We need to come up with better API here.
*/
#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
/**
* Calculates the horizontal sync rate of a mode.
*
* Exact copy of xf86Mode.c's.
*/
double
xf86ModeHSync(DisplayModePtr mode)
{
double hsync = 0.0;
if (mode->HSync > 0.0)
hsync = mode->HSync;
else if (mode->HTotal > 0)
hsync = (float)mode->Clock / (float)mode->HTotal;
return hsync;
}
/**
* Calculates the vertical refresh rate of a mode.
*
* Exact copy of xf86Mode.c's.
*/
double
xf86ModeVRefresh(DisplayModePtr mode)
{
double refresh = 0.0;
if (mode->VRefresh > 0.0)
refresh = mode->VRefresh;
else if (mode->HTotal > 0 && mode->VTotal > 0) {
refresh = mode->Clock * 1000.0 / mode->HTotal / mode->VTotal;
if (mode->Flags & V_INTERLACE)
refresh *= 2.0;
if (mode->Flags & V_DBLSCAN)
refresh /= 2.0;
if (mode->VScan > 1)
refresh /= (float)(mode->VScan);
}
return refresh;
}
/** Sets a default mode name of <width>x<height> on a mode. */
void
xf86SetModeDefaultName(DisplayModePtr mode)
{
if (mode->name != NULL)
xfree(mode->name);
mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay);
}
/*
* xf86SetModeCrtc
*
* Initialises the Crtc parameters for a mode. The initialisation includes
* adjustments for interlaced and double scan modes.
*
* Exact copy of xf86Mode.c's.
*/
void
xf86SetModeCrtc(DisplayModePtr p, int adjustFlags)
{
if ((p == NULL) || ((p->type & M_T_CRTC_C) == M_T_BUILTIN))
return;
p->CrtcHDisplay = p->HDisplay;
p->CrtcHSyncStart = p->HSyncStart;
p->CrtcHSyncEnd = p->HSyncEnd;
p->CrtcHTotal = p->HTotal;
p->CrtcHSkew = p->HSkew;
p->CrtcVDisplay = p->VDisplay;
p->CrtcVSyncStart = p->VSyncStart;
p->CrtcVSyncEnd = p->VSyncEnd;
p->CrtcVTotal = p->VTotal;
if (p->Flags & V_INTERLACE) {
if (adjustFlags & INTERLACE_HALVE_V) {
p->CrtcVDisplay /= 2;
p->CrtcVSyncStart /= 2;
p->CrtcVSyncEnd /= 2;
p->CrtcVTotal /= 2;
}
/* Force interlaced modes to have an odd VTotal */
/* maybe we should only do this when INTERLACE_HALVE_V is set? */
p->CrtcVTotal |= 1;
}
if (p->Flags & V_DBLSCAN) {
p->CrtcVDisplay *= 2;
p->CrtcVSyncStart *= 2;
p->CrtcVSyncEnd *= 2;
p->CrtcVTotal *= 2;
}
if (p->VScan > 1) {
p->CrtcVDisplay *= p->VScan;
p->CrtcVSyncStart *= p->VScan;
p->CrtcVSyncEnd *= p->VScan;
p->CrtcVTotal *= p->VScan;
}
p->CrtcVBlankStart = min(p->CrtcVSyncStart, p->CrtcVDisplay);
p->CrtcVBlankEnd = max(p->CrtcVSyncEnd, p->CrtcVTotal);
p->CrtcHBlankStart = min(p->CrtcHSyncStart, p->CrtcHDisplay);
p->CrtcHBlankEnd = max(p->CrtcHSyncEnd, p->CrtcHTotal);
p->CrtcHAdjusted = FALSE;
p->CrtcVAdjusted = FALSE;
}
/**
* Allocates and returns a copy of pMode, including pointers within pMode.
*/
DisplayModePtr
xf86DuplicateMode(DisplayModePtr pMode)
{
DisplayModePtr pNew;
pNew = xnfalloc(sizeof(DisplayModeRec));
*pNew = *pMode;
pNew->next = NULL;
pNew->prev = NULL;
if (pNew->name == NULL) {
xf86SetModeDefaultName(pMode);
} else {
pNew->name = xnfstrdup(pMode->name);
}
return pNew;
}
/**
* Duplicates every mode in the given list and returns a pointer to the first
* mode.
*
* \param modeList doubly-linked mode list
*/
DisplayModePtr
xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList)
{
DisplayModePtr first = NULL, last = NULL;
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
DisplayModePtr new;
new = xf86DuplicateMode(mode);
/* Insert pNew into modeList */
if (last) {
last->next = new;
new->prev = last;
} else {
first = new;
new->prev = NULL;
}
new->next = NULL;
last = new;
}
return first;
}
/**
* Returns true if the given modes should program to the same timings.
*
* This doesn't use Crtc values, as it might be used on ModeRecs without the
* Crtc values set. So, it's assumed that the other numbers are enough.
*
* This isn't in xf86Modes.c, but it might deserve to be there.
*/
Bool
xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2)
{
if (pMode1->Clock == pMode2->Clock &&
pMode1->HDisplay == pMode2->HDisplay &&
pMode1->HSyncStart == pMode2->HSyncStart &&
pMode1->HSyncEnd == pMode2->HSyncEnd &&
pMode1->HTotal == pMode2->HTotal &&
pMode1->HSkew == pMode2->HSkew &&
pMode1->VDisplay == pMode2->VDisplay &&
pMode1->VSyncStart == pMode2->VSyncStart &&
pMode1->VSyncEnd == pMode2->VSyncEnd &&
pMode1->VTotal == pMode2->VTotal &&
pMode1->VScan == pMode2->VScan &&
pMode1->Flags == pMode2->Flags)
{
return TRUE;
} else {
return FALSE;
}
}
/* exact copy of xf86Mode.c */
static void
add(char **p, char *new)
{
*p = xnfrealloc(*p, strlen(*p) + strlen(new) + 2);
strcat(*p, " ");
strcat(*p, new);
}
/**
* Print out a modeline.
*
* Convenient VRefresh printing was added, though, compared to xf86Mode.c
*/
void
xf86PrintModeline(int scrnIndex,DisplayModePtr mode)
{
char tmp[256];
char *flags = xnfcalloc(1, 1);
if (mode->HSkew) {
snprintf(tmp, 256, "hskew %i", mode->HSkew);
add(&flags, tmp);
}
if (mode->VScan) {
snprintf(tmp, 256, "vscan %i", mode->VScan);
add(&flags, tmp);
}
if (mode->Flags & V_INTERLACE) add(&flags, "interlace");
if (mode->Flags & V_CSYNC) add(&flags, "composite");
if (mode->Flags & V_DBLSCAN) add(&flags, "doublescan");
if (mode->Flags & V_BCAST) add(&flags, "bcast");
if (mode->Flags & V_PHSYNC) add(&flags, "+hsync");
if (mode->Flags & V_NHSYNC) add(&flags, "-hsync");
if (mode->Flags & V_PVSYNC) add(&flags, "+vsync");
if (mode->Flags & V_NVSYNC) add(&flags, "-vsync");
if (mode->Flags & V_PCSYNC) add(&flags, "+csync");
if (mode->Flags & V_NCSYNC) add(&flags, "-csync");
#if 0
if (mode->Flags & V_CLKDIV2) add(&flags, "vclk/2");
#endif
xf86DrvMsg(scrnIndex, X_INFO,
"Modeline \"%s\"x%.01f %6.2f %i %i %i %i %i %i %i %i%s "
"(%.01f kHz)\n",
mode->name, mode->VRefresh, mode->Clock/1000., mode->HDisplay,
mode->HSyncStart, mode->HSyncEnd, mode->HTotal,
mode->VDisplay, mode->VSyncStart, mode->VSyncEnd,
mode->VTotal, flags, xf86ModeHSync(mode));
xfree(flags);
}
#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
/**
* Marks as bad any modes with unsupported flags.
*
* \param modeList doubly-linked or circular list of modes.
* \param flags flags supported by the driver.
*
* \bug only V_INTERLACE and V_DBLSCAN are supported. Is that enough?
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags)
{
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
if (mode->Flags & V_INTERLACE && !(flags & V_INTERLACE))
mode->status = MODE_NO_INTERLACE;
if (mode->Flags & V_DBLSCAN && !(flags & V_DBLSCAN))
mode->status = MODE_NO_DBLESCAN;
}
}
/**
* Marks as bad any modes extending beyond the given max X, Y, or pitch.
*
* \param modeList doubly-linked or circular list of modes.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int maxX, int maxY, int maxPitch)
{
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
if (maxPitch > 0 && mode->HDisplay > maxPitch)
mode->status = MODE_BAD_WIDTH;
if (maxX > 0 && mode->HDisplay > maxX)
mode->status = MODE_VIRTUAL_X;
if (maxY > 0 && mode->VDisplay > maxY)
mode->status = MODE_VIRTUAL_Y;
if (mode->next == modeList)
break;
}
}
/**
* Marks as bad any modes that aren't supported by the given monitor's
* hsync and vrefresh ranges.
*
* \param modeList doubly-linked or circular list of modes.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
MonPtr mon)
{
DisplayModePtr mode;
for (mode = modeList; mode != NULL; mode = mode->next) {
Bool bad;
int i;
bad = TRUE;
for (i = 0; i < mon->nHsync; i++) {
if (xf86ModeHSync(mode) >= mon->hsync[i].lo &&
xf86ModeHSync(mode) <= mon->hsync[i].hi)
{
bad = FALSE;
}
}
if (bad)
mode->status = MODE_HSYNC;
bad = TRUE;
for (i = 0; i < mon->nVrefresh; i++) {
if (xf86ModeVRefresh(mode) >= mon->vrefresh[i].lo &&
xf86ModeVRefresh(mode) <= mon->vrefresh[i].hi)
{
bad = FALSE;
}
}
if (bad)
mode->status = MODE_VSYNC;
if (mode->next == modeList)
break;
}
}
/**
* Marks as bad any modes extending beyond outside of the given clock ranges.
*
* \param modeList doubly-linked or circular list of modes.
* \param min pointer to minimums of clock ranges
* \param max pointer to maximums of clock ranges
* \param n_ranges number of ranges.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int *min, int *max, int n_ranges)
{
DisplayModePtr mode;
int i;
for (mode = modeList; mode != NULL; mode = mode->next) {
Bool good = FALSE;
for (i = 0; i < n_ranges; i++) {
if (mode->Clock >= min[i] && mode->Clock <= max[i]) {
good = TRUE;
break;
}
}
if (!good)
mode->status = MODE_CLOCK_RANGE;
}
}
/**
* If the user has specified a set of mode names to use, mark as bad any modes
* not listed.
*
* The user mode names specified are prefixes to names of modes, so "1024x768"
* will match modes named "1024x768", "1024x768x75", "1024x768-good", but
* "1024x768x75" would only match "1024x768x75" from that list.
*
* MODE_BAD is used as the rejection flag, for lack of a better flag.
*
* \param modeList doubly-linked or circular list of modes.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
{
DisplayModePtr mode;
if (pScrn->display->modes[0] == NULL)
return;
for (mode = modeList; mode != NULL; mode = mode->next) {
int i;
Bool good = FALSE;
for (i = 0; pScrn->display->modes[i] != NULL; i++) {
if (strncmp(pScrn->display->modes[i], mode->name,
strlen(pScrn->display->modes[i])) == 0) {
good = TRUE;
break;
}
}
if (!good)
mode->status = MODE_BAD;
}
}
/**
* Frees any modes from the list with a status other than MODE_OK.
*
* \param modeList pointer to a doubly-linked or circular list of modes.
* \param verbose determines whether the reason for mode invalidation is
* printed.
*
* This is not in xf86Modes.c, but would be part of the proposed new API.
*/
void
xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
Bool verbose)
{
DisplayModePtr mode;
for (mode = *modeList; mode != NULL;) {
DisplayModePtr next = mode->next, first = *modeList;
if (mode->status != MODE_OK) {
if (verbose) {
char *type = "";
if (mode->type & M_T_BUILTIN)
type = "built-in ";
else if (mode->type & M_T_DEFAULT)
type = "default ";
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Not using %smode \"%s\" (%s)\n", type, mode->name,
xf86ModeStatusToString(mode->status));
}
xf86DeleteMode(modeList, mode);
}
if (next == first)
break;
mode = next;
}
}
/**
* Adds the new mode into the mode list, and returns the new list
*
* \param modes doubly-linked mode list.
*/
DisplayModePtr
xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new)
{
if (modes == NULL)
return new;
if (new) {
DisplayModePtr mode = modes;
while (mode->next)
mode = mode->next;
mode->next = new;
new->prev = mode;
}
return modes;
}
/**
* Build a mode list from a list of config file modes
*/
static DisplayModePtr
xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
{
DisplayModePtr head = NULL, prev = NULL, mode;
for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
{
mode = xcalloc(1, sizeof(DisplayModeRec));
if (!mode)
continue;
mode->name = xstrdup(conf_mode->ml_identifier);
if (!mode->name)
{
xfree (mode);
continue;
}
mode->type = 0;
mode->Clock = conf_mode->ml_clock;
mode->HDisplay = conf_mode->ml_hdisplay;
mode->HSyncStart = conf_mode->ml_hsyncstart;
mode->HSyncEnd = conf_mode->ml_hsyncend;
mode->HTotal = conf_mode->ml_htotal;
mode->VDisplay = conf_mode->ml_vdisplay;
mode->VSyncStart = conf_mode->ml_vsyncstart;
mode->VSyncEnd = conf_mode->ml_vsyncend;
mode->VTotal = conf_mode->ml_vtotal;
mode->Flags = conf_mode->ml_flags;
mode->HSkew = conf_mode->ml_hskew;
mode->VScan = conf_mode->ml_vscan;
mode->prev = prev;
mode->next = NULL;
if (prev)
prev->next = mode;
else
head = mode;
prev = mode;
}
return head;
}
/**
* Build a mode list from a monitor configuration
*/
DisplayModePtr
xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
{
DisplayModePtr modes = NULL;
XF86ConfModesLinkPtr modes_link;
if (!conf_monitor)
return NULL;
/*
* first we collect the mode lines from the UseModes directive
*/
for (modes_link = conf_monitor->mon_modes_sect_lst;
modes_link;
modes_link = modes_link->list.next)
{
/* If this modes link hasn't been resolved, go look it up now */
if (!modes_link->ml_modes)
modes_link->ml_modes = xf86findModes (modes_link->ml_modes_str,
xf86configptr->conf_modes_lst);
if (modes_link->ml_modes)
modes = xf86ModesAdd (modes,
xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
}
return xf86ModesAdd (modes,
xf86GetConfigModes (conf_monitor->mon_modeline_lst));
}
/**
* Build a mode list containing all of the default modes
*/
DisplayModePtr
xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
{
DisplayModePtr head = NULL, prev = NULL, mode;
int i;
for (i = 0; xf86DefaultModes[i].name != NULL; i++)
{
DisplayModePtr defMode = &xf86DefaultModes[i];
if (!interlaceAllowed && (defMode->Flags & V_INTERLACE))
continue;
if (!doubleScanAllowed && (defMode->Flags & V_DBLSCAN))
continue;
mode = xalloc(sizeof(DisplayModeRec));
if (!mode)
continue;
memcpy(mode,&xf86DefaultModes[i],sizeof(DisplayModeRec));
mode->name = xstrdup(xf86DefaultModes[i].name);
if (!mode->name)
{
xfree (mode);
continue;
}
mode->prev = prev;
mode->next = NULL;
if (prev)
prev->next = mode;
else
head = mode;
prev = mode;
}
return head;
}

View File

@ -0,0 +1,85 @@
/*
* Copyright © 2006 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
#ifndef _I830_XF86MODES_H_
#define _I830_XF86MODES_H_
#include "xorgVersion.h"
#include "xf86Parser.h"
#include "edid.h"
#if XF86_MODES_RENAME
#include "xf86Rename.h"
#endif
double xf86ModeHSync(DisplayModePtr mode);
double xf86ModeVRefresh(DisplayModePtr mode);
DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode);
DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn,
DisplayModePtr modeList);
void xf86SetModeDefaultName(DisplayModePtr mode);
void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
void xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
Bool Reduced, Bool Interlaced);
void
xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags);
void
xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int *min, int *max, int n_ranges);
void
xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int maxX, int maxY, int maxPitch);
void
xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
MonPtr mon);
void
xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
Bool verbose);
void
xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
int flags);
void
xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
DisplayModePtr
xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
DisplayModePtr
xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
#endif /* _I830_XF86MODES_H_ */

View File

@ -0,0 +1,950 @@
/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.3 2004/07/30 21:53:09 eich Exp $ */
/*
* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86RandR.c,v 1.7tsi Exp $
*
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
*
* 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>
#endif
#include "xf86.h"
#include "os.h"
#include "mibank.h"
#include "globals.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86DDC.h"
#include "mipointer.h"
#include "windowstr.h"
#include <randrstr.h>
#include <X11/extensions/render.h>
#include "xf86Crtc.h"
#include "xf86RandR12.h"
typedef struct _xf86RandR12Info {
int virtualX;
int virtualY;
int mmWidth;
int mmHeight;
int maxX;
int maxY;
Rotation rotation; /* current mode */
Rotation supported_rotations; /* driver supported */
} XF86RandRInfoRec, *XF86RandRInfoPtr;
#ifdef RANDR_12_INTERFACE
static Bool xf86RandR12Init12 (ScreenPtr pScreen);
static Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen);
#endif
static int xf86RandR12Index;
static int xf86RandR12Generation;
#define XF86RANDRINFO(p) \
((XF86RandRInfoPtr)(p)->devPrivates[xf86RandR12Index].ptr)
static int
xf86RandR12ModeRefresh (DisplayModePtr mode)
{
if (mode->VRefresh)
return (int) (mode->VRefresh + 0.5);
else
return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
}
static Bool
xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
{
RRScreenSizePtr pSize;
ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
DisplayModePtr mode;
int refresh0 = 60;
int maxX = 0, maxY = 0;
*rotations = randrp->supported_rotations;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = scrp->virtualX;
randrp->virtualY = scrp->virtualY;
}
/* Re-probe the outputs for new monitors or modes */
xf86ProbeOutputModes (scrp, 0, 0);
xf86SetScrnInfoModes (scrp);
xf86DiDGAReInit (pScreen);
for (mode = scrp->modes; ; mode = mode->next)
{
int refresh = xf86RandR12ModeRefresh (mode);
if (randrp->maxX == 0 || randrp->maxY == 0)
{
if (maxX < mode->HDisplay)
maxX = mode->HDisplay;
if (maxY < mode->VDisplay)
maxY = mode->VDisplay;
}
if (mode == scrp->modes)
refresh0 = refresh;
pSize = RRRegisterSize (pScreen,
mode->HDisplay, mode->VDisplay,
randrp->mmWidth, randrp->mmHeight);
if (!pSize)
return FALSE;
RRRegisterRate (pScreen, pSize, refresh);
if (xf86ModesEqual(mode, scrp->currentMode) &&
mode->HDisplay == scrp->virtualX &&
mode->VDisplay == scrp->virtualY)
{
RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize);
}
if (mode->next == scrp->modes)
break;
}
if (randrp->maxX == 0 || randrp->maxY == 0)
{
randrp->maxX = maxX;
randrp->maxY = maxY;
}
if (scrp->currentMode->HDisplay != randrp->virtualX ||
scrp->currentMode->VDisplay != randrp->virtualY)
{
pSize = RRRegisterSize (pScreen,
randrp->virtualX, randrp->virtualY,
randrp->mmWidth,
randrp->mmHeight);
if (!pSize)
return FALSE;
RRRegisterRate (pScreen, pSize, refresh0);
if (scrp->virtualX == randrp->virtualX &&
scrp->virtualY == randrp->virtualY)
{
RRSetCurrentConfig (pScreen, randrp->rotation, refresh0, pSize);
}
}
return TRUE;
}
static Bool
xf86RandR12SetMode (ScreenPtr pScreen,
DisplayModePtr mode,
Bool useVirtual,
int mmWidth,
int mmHeight)
{
ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
int oldWidth = pScreen->width;
int oldHeight = pScreen->height;
int oldmmWidth = pScreen->mmWidth;
int oldmmHeight = pScreen->mmHeight;
WindowPtr pRoot = WindowTable[pScreen->myNum];
DisplayModePtr currentMode = NULL;
Bool ret = TRUE;
PixmapPtr pspix = NULL;
if (pRoot)
(*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE);
if (useVirtual)
{
scrp->virtualX = randrp->virtualX;
scrp->virtualY = randrp->virtualY;
}
else
{
scrp->virtualX = mode->HDisplay;
scrp->virtualY = mode->VDisplay;
}
if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270))
{
/* If the screen is rotated 90 or 270 degrees, swap the sizes. */
pScreen->width = scrp->virtualY;
pScreen->height = scrp->virtualX;
pScreen->mmWidth = mmHeight;
pScreen->mmHeight = mmWidth;
}
else
{
pScreen->width = scrp->virtualX;
pScreen->height = scrp->virtualY;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;
}
if (scrp->currentMode == mode) {
/* Save current mode */
currentMode = scrp->currentMode;
/* Reset, just so we ensure the drivers SwitchMode is called */
scrp->currentMode = NULL;
}
/*
* We know that if the driver failed to SwitchMode to the rotated
* version, then it should revert back to it's prior mode.
*/
if (!xf86SwitchMode (pScreen, mode))
{
ret = FALSE;
scrp->virtualX = pScreen->width = oldWidth;
scrp->virtualY = pScreen->height = oldHeight;
pScreen->mmWidth = oldmmWidth;
pScreen->mmHeight = oldmmHeight;
scrp->currentMode = currentMode;
}
/*
* Get the new Screen pixmap ptr as SwitchMode might have called
* ModifyPixmapHeader and xf86EnableDisableFBAccess will put it back...
* Unfortunately.
*/
pspix = (*pScreen->GetScreenPixmap) (pScreen);
if (pspix->devPrivate.ptr)
scrp->pixmapPrivate = pspix->devPrivate;
/*
* Make sure the layout is correct
*/
xf86ReconfigureLayout();
/*
* Make sure the whole screen is visible
*/
xf86SetViewport (pScreen, pScreen->width, pScreen->height);
xf86SetViewport (pScreen, 0, 0);
if (pRoot)
(*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE);
return ret;
}
Bool
xf86RandR12SetConfig (ScreenPtr pScreen,
Rotation rotation,
int rate,
RRScreenSizePtr pSize)
{
ScrnInfoPtr scrp = XF86SCRNINFO(pScreen);
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
DisplayModePtr mode;
int px, py;
Bool useVirtual = FALSE;
int maxX = 0, maxY = 0;
Rotation oldRotation = randrp->rotation;
randrp->rotation = rotation;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = scrp->virtualX;
randrp->virtualY = scrp->virtualY;
}
miPointerPosition (&px, &py);
for (mode = scrp->modes; ; mode = mode->next)
{
if (randrp->maxX == 0 || randrp->maxY == 0)
{
if (maxX < mode->HDisplay)
maxX = mode->HDisplay;
if (maxY < mode->VDisplay)
maxY = mode->VDisplay;
}
if (mode->HDisplay == pSize->width &&
mode->VDisplay == pSize->height &&
(rate == 0 || xf86RandR12ModeRefresh (mode) == rate))
break;
if (mode->next == scrp->modes)
{
if (pSize->width == randrp->virtualX &&
pSize->height == randrp->virtualY)
{
mode = scrp->modes;
useVirtual = TRUE;
break;
}
if (randrp->maxX == 0 || randrp->maxY == 0)
{
randrp->maxX = maxX;
randrp->maxY = maxY;
}
return FALSE;
}
}
if (randrp->maxX == 0 || randrp->maxY == 0)
{
randrp->maxX = maxX;
randrp->maxY = maxY;
}
if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth,
pSize->mmHeight)) {
randrp->rotation = oldRotation;
return FALSE;
}
/*
* Move the cursor back where it belongs; SwitchMode repositions it
*/
if (pScreen == miPointerCurrentScreen ())
{
px = (px >= pScreen->width ? (pScreen->width - 1) : px);
py = (py >= pScreen->height ? (pScreen->height - 1) : py);
xf86SetViewport(pScreen, px, py);
(*pScreen->SetCursorPosition) (pScreen, px, py, FALSE);
}
return TRUE;
}
static Bool
xf86RandR12ScreenSetSize (ScreenPtr pScreen,
CARD16 width,
CARD16 height,
CARD32 mmWidth,
CARD32 mmHeight)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
WindowPtr pRoot = WindowTable[pScreen->myNum];
Bool ret = TRUE;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = pScrn->virtualX;
randrp->virtualY = pScrn->virtualY;
}
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
pScrn->virtualX = width;
pScrn->virtualY = height;
pScreen->width = pScrn->virtualX;
pScreen->height = pScrn->virtualY;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;
xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
xf86SetViewport (pScreen, 0, 0);
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
#if RANDR_12_INTERFACE
if (WindowTable[pScreen->myNum])
RRScreenSizeNotify (pScreen);
#endif
return ret;
}
Rotation
xf86RandR12GetRotation(ScreenPtr pScreen)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
return randrp->rotation;
}
Bool
xf86RandR12CreateScreenResources (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
int c;
int width, height;
int mmWidth, mmHeight;
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension)
return TRUE;
#endif
/*
* Compute size of screen
*/
width = 0; height = 0;
for (c = 0; c < config->num_crtc; c++)
{
xf86CrtcPtr crtc = config->crtc[c];
int crtc_width = crtc->x + crtc->mode.HDisplay;
int crtc_height = crtc->y + crtc->mode.VDisplay;
if (crtc->enabled && crtc_width > width)
width = crtc_width;
if (crtc->enabled && crtc_height > height)
height = crtc_height;
}
if (width && height)
{
/*
* Compute physical size of screen
*/
if (monitorResolution)
{
mmWidth = width * 25.4 / monitorResolution;
mmHeight = height * 25.4 / monitorResolution;
}
else
{
mmWidth = pScreen->mmWidth;
mmHeight = pScreen->mmHeight;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Setting screen physical size to %d x %d\n",
mmWidth, mmHeight);
xf86RandR12ScreenSetSize (pScreen,
width,
height,
mmWidth,
mmHeight);
}
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
randrp->virtualX = pScrn->virtualX;
randrp->virtualY = pScrn->virtualY;
}
#if RANDR_12_INTERFACE
if (xf86RandR12CreateScreenResources12 (pScreen))
return TRUE;
#endif
return TRUE;
}
Bool
xf86RandR12Init (ScreenPtr pScreen)
{
rrScrPrivPtr rp;
XF86RandRInfoPtr randrp;
#ifdef PANORAMIX
/* XXX disable RandR when using Xinerama */
if (!noPanoramiXExtension)
return TRUE;
#endif
if (xf86RandR12Generation != serverGeneration)
{
xf86RandR12Index = AllocateScreenPrivateIndex();
xf86RandR12Generation = serverGeneration;
}
randrp = xalloc (sizeof (XF86RandRInfoRec));
if (!randrp)
return FALSE;
if (!RRScreenInit(pScreen))
{
xfree (randrp);
return FALSE;
}
rp = rrGetScrPriv(pScreen);
rp->rrGetInfo = xf86RandR12GetInfo;
rp->rrSetConfig = xf86RandR12SetConfig;
randrp->virtualX = -1;
randrp->virtualY = -1;
randrp->mmWidth = pScreen->mmWidth;
randrp->mmHeight = pScreen->mmHeight;
randrp->rotation = RR_Rotate_0; /* initial rotated mode */
randrp->supported_rotations = RR_Rotate_0;
randrp->maxX = randrp->maxY = 0;
pScreen->devPrivates[xf86RandR12Index].ptr = randrp;
#if RANDR_12_INTERFACE
if (!xf86RandR12Init12 (pScreen))
return FALSE;
#endif
return TRUE;
}
void
xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
randrp->supported_rotations = rotations;
#if RANDR_12_INTERFACE
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
RRCrtcSetRotations (crtc->randr_crtc, rotations);
}
#endif
}
void
xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
{
ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
if (xf86RandR12Generation != serverGeneration ||
XF86RANDRINFO(pScreen)->virtualX == -1)
{
*x = pScrn->virtualX;
*y = pScrn->virtualY;
} else {
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
*x = randrp->virtualX;
*y = randrp->virtualY;
}
}
#if RANDR_12_INTERFACE
static Bool
xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc)
{
ScreenPtr pScreen = randr_crtc->pScreen;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
RRModePtr randr_mode = NULL;
int x;
int y;
Rotation rotation;
int numOutputs;
RROutputPtr *randr_outputs;
RROutputPtr randr_output;
xf86CrtcPtr crtc = randr_crtc->devPrivate;
xf86OutputPtr output;
int i, j;
DisplayModePtr mode = &crtc->mode;
Bool ret;
randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
if (!randr_outputs)
return FALSE;
x = crtc->x;
y = crtc->y;
rotation = crtc->rotation;
numOutputs = 0;
randr_mode = NULL;
for (i = 0; i < config->num_output; i++)
{
output = config->output[i];
if (output->crtc == crtc)
{
randr_output = output->randr_output;
randr_outputs[numOutputs++] = randr_output;
/*
* We make copies of modes, so pointer equality
* isn't sufficient
*/
for (j = 0; j < randr_output->numModes; j++)
{
DisplayModePtr outMode = randr_output->modes[j]->devPrivate;
if (xf86ModesEqual(mode, outMode))
{
randr_mode = randr_output->modes[j];
break;
}
}
}
}
ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
rotation, numOutputs, randr_outputs);
DEALLOCATE_LOCAL(randr_outputs);
return ret;
}
static Bool
xf86RandR12CrtcSet (ScreenPtr pScreen,
RRCrtcPtr randr_crtc,
RRModePtr randr_mode,
int x,
int y,
Rotation rotation,
int num_randr_outputs,
RROutputPtr *randr_outputs)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr crtc = randr_crtc->devPrivate;
DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL;
Bool changed = FALSE;
int o, ro;
xf86CrtcPtr *save_crtcs;
Bool save_enabled = crtc->enabled;
save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
if ((mode != NULL) != crtc->enabled)
changed = TRUE;
else if (mode && !xf86ModesEqual (&crtc->mode, mode))
changed = TRUE;
if (rotation != crtc->rotation)
changed = TRUE;
if (x != crtc->x || y != crtc->y)
changed = TRUE;
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
xf86CrtcPtr new_crtc;
save_crtcs[o] = output->crtc;
if (output->crtc == crtc)
new_crtc = NULL;
else
new_crtc = output->crtc;
for (ro = 0; ro < num_randr_outputs; ro++)
if (output->randr_output == randr_outputs[ro])
{
new_crtc = crtc;
break;
}
if (new_crtc != output->crtc)
{
changed = TRUE;
output->crtc = new_crtc;
}
}
/* XXX need device-independent mode setting code through an API */
if (changed)
{
crtc->enabled = mode != NULL;
if (mode)
{
if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
{
crtc->enabled = save_enabled;
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
output->crtc = save_crtcs[o];
}
DEALLOCATE_LOCAL(save_crtcs);
return FALSE;
}
/*
* Save the last successful setting for EnterVT
*/
crtc->desiredMode = *mode;
crtc->desiredRotation = rotation;
crtc->desiredX = x;
crtc->desiredY = y;
}
xf86DisableUnusedFunctions (pScrn);
}
DEALLOCATE_LOCAL(save_crtcs);
return xf86RandR12CrtcNotify (randr_crtc);
}
static Bool
xf86RandR12CrtcSetGamma (ScreenPtr pScreen,
RRCrtcPtr randr_crtc)
{
xf86CrtcPtr crtc = randr_crtc->devPrivate;
if (crtc->funcs->gamma_set == NULL)
return FALSE;
crtc->funcs->gamma_set(crtc, randr_crtc->gammaRed, randr_crtc->gammaGreen,
randr_crtc->gammaBlue, randr_crtc->gammaSize);
return TRUE;
}
static Bool
xf86RandR12OutputSetProperty (ScreenPtr pScreen,
RROutputPtr randr_output,
Atom property,
RRPropertyValuePtr value)
{
xf86OutputPtr output = randr_output->devPrivate;
/* If we don't have any property handler, then we don't care what the
* user is setting properties to.
*/
if (output->funcs->set_property == NULL)
return TRUE;
return output->funcs->set_property(output, property, value);
}
/**
* Given a list of xf86 modes and a RandR Output object, construct
* RandR modes and assign them to the output
*/
static Bool
xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
{
DisplayModePtr mode;
RRModePtr *rrmodes = NULL;
int nmode = 0;
int npreferred = 0;
Bool ret = TRUE;
int pref;
for (mode = modes; mode; mode = mode->next)
nmode++;
if (nmode) {
rrmodes = xalloc (nmode * sizeof (RRModePtr));
if (!rrmodes)
return FALSE;
nmode = 0;
for (pref = 1; pref >= 0; pref--) {
for (mode = modes; mode; mode = mode->next) {
if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
xRRModeInfo modeInfo;
RRModePtr rrmode;
modeInfo.nameLength = strlen (mode->name);
modeInfo.width = mode->HDisplay;
modeInfo.dotClock = mode->Clock * 1000;
modeInfo.hSyncStart = mode->HSyncStart;
modeInfo.hSyncEnd = mode->HSyncEnd;
modeInfo.hTotal = mode->HTotal;
modeInfo.hSkew = mode->HSkew;
modeInfo.height = mode->VDisplay;
modeInfo.vSyncStart = mode->VSyncStart;
modeInfo.vSyncEnd = mode->VSyncEnd;
modeInfo.vTotal = mode->VTotal;
modeInfo.modeFlags = mode->Flags;
rrmode = RRModeGet (&modeInfo, mode->name);
if (rrmode) {
rrmode->devPrivate = mode;
rrmodes[nmode++] = rrmode;
npreferred += pref;
}
}
}
}
}
ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
xfree (rrmodes);
return ret;
}
/*
* Mirror the current mode configuration to RandR
*/
static Bool
xf86RandR12SetInfo12 (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
RROutputPtr *clones;
RRCrtcPtr *crtcs;
int ncrtc;
int o, c, l;
RRCrtcPtr randr_crtc;
int nclone;
clones = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
crtcs = ALLOCATE_LOCAL (config->num_crtc * sizeof (RRCrtcPtr));
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
ncrtc = 0;
for (c = 0; c < config->num_crtc; c++)
if (output->possible_crtcs & (1 << c))
crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
if (output->crtc)
randr_crtc = output->crtc->randr_crtc;
else
randr_crtc = NULL;
if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc))
{
DEALLOCATE_LOCAL (crtcs);
DEALLOCATE_LOCAL (clones);
return FALSE;
}
RROutputSetCrtc (output->randr_output, randr_crtc);
RROutputSetPhysicalSize(output->randr_output,
output->mm_width,
output->mm_height);
xf86RROutputSetModes (output->randr_output, output->probed_modes);
switch (output->status) {
case XF86OutputStatusConnected:
RROutputSetConnection (output->randr_output, RR_Connected);
break;
case XF86OutputStatusDisconnected:
RROutputSetConnection (output->randr_output, RR_Disconnected);
break;
case XF86OutputStatusUnknown:
RROutputSetConnection (output->randr_output, RR_UnknownConnection);
break;
}
RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order);
/*
* Valid clones
*/
nclone = 0;
for (l = 0; l < config->num_output; l++)
{
xf86OutputPtr clone = config->output[l];
if (l != o && (output->possible_clones & (1 << l)))
clones[nclone++] = clone->randr_output;
}
if (!RROutputSetClones (output->randr_output, clones, nclone))
{
DEALLOCATE_LOCAL (crtcs);
DEALLOCATE_LOCAL (clones);
return FALSE;
}
}
DEALLOCATE_LOCAL (crtcs);
DEALLOCATE_LOCAL (clones);
return TRUE;
}
/*
* Query the hardware for the current state, then mirror
* that to RandR
*/
static Bool
xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86ProbeOutputModes (pScrn, 0, 0);
xf86SetScrnInfoModes (pScrn);
xf86DiDGAReInit (pScreen);
return xf86RandR12SetInfo12 (pScreen);
}
static Bool
xf86RandR12CreateObjects12 (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
int o;
if (!RRInit ())
return FALSE;
/*
* Configure crtcs
*/
for (c = 0; c < config->num_crtc; c++)
{
xf86CrtcPtr crtc = config->crtc[c];
crtc->randr_crtc = RRCrtcCreate (crtc);
RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
RRCrtcGammaSetSize (crtc->randr_crtc, 256);
}
/*
* Configure outputs
*/
for (o = 0; o < config->num_output; o++)
{
xf86OutputPtr output = config->output[o];
output->randr_output = RROutputCreate (output->name,
strlen (output->name),
output);
RROutputAttachScreen (output->randr_output, pScreen);
if (output->funcs->create_resources != NULL)
output->funcs->create_resources(output);
}
return TRUE;
}
static Bool
xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
{
int c;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
for (c = 0; c < config->num_crtc; c++)
xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
RRScreenSetSizeRange (pScreen, 320, 240,
randrp->virtualX, randrp->virtualY);
return TRUE;
}
static void
xf86RandR12PointerMoved (int scrnIndex, int x, int y)
{
}
static Bool
xf86RandR12Init12 (ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
rrScrPrivPtr rp = rrGetScrPriv(pScreen);
rp->rrGetInfo = xf86RandR12GetInfo12;
rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
rp->rrCrtcSet = xf86RandR12CrtcSet;
rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
rp->rrSetConfig = NULL;
pScrn->PointerMoved = xf86RandR12PointerMoved;
if (!xf86RandR12CreateObjects12 (pScreen))
return FALSE;
/*
* Configure output modes
*/
if (!xf86RandR12SetInfo12 (pScreen))
return FALSE;
return TRUE;
}
#endif
Bool
xf86RandR12PreInit (ScrnInfoPtr pScrn)
{
return TRUE;
}

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
#ifndef _XF86_RANDR_H_
#define _XF86_RANDR_H_
#include <randrstr.h>
#include <X11/extensions/render.h>
Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
Bool xf86RandR12Init(ScreenPtr pScreen);
void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
RRScreenSizePtr pSize);
Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
void xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
Bool xf86RandR12PreInit (ScrnInfoPtr pScrn);
#endif /* _XF86_RANDR_H_ */

View File

@ -0,0 +1,77 @@
/*
* 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.
*/
#ifndef _XF86RENAME_H_
#define _XF86RENAME_H_
#include "local_xf86Rename.h"
#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit)
#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex)
#define xf86CrtcCreate XF86NAME(xf86CrtcCreate)
#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy)
#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
#define xf86CVTMode XF86NAME(xf86CVTMode)
#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions)
#define xf86DPMSSet XF86NAME(xf86DPMSSet)
#define xf86DuplicateMode XF86NAME(xf86DuplicateMode)
#define xf86DuplicateModes XF86NAME(xf86DuplicateModes)
#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes)
#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes)
#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration)
#define xf86ModeHSync XF86NAME(xf86ModeHSync)
#define xf86ModesAdd XF86NAME(xf86ModesAdd)
#define xf86ModesEqual XF86NAME(xf86ModesEqual)
#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh)
#define xf86OutputCreate XF86NAME(xf86OutputCreate)
#define xf86OutputDestroy XF86NAME(xf86OutputDestroy)
#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID)
#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes)
#define xf86OutputRename XF86NAME(xf86OutputRename)
#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID)
#define xf86PrintModeline XF86NAME(xf86PrintModeline)
#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes)
#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes)
#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc)
#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName)
#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes)
#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks)
#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags)
#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
#define xf86DiDGAInit XF86NAME(xf86DiDGAInit)
#define xf86DiDGAReInit XF86NAME(xf86DiDGAReInit)
#define xf86DDCGetModes XF86NAME(xf86DDCGetModes)
#define xf86RandR12CreateScreenResources XF86NAME(xf86RandR12CreateScreenResources)
#define xf86RandR12GetOriginalVirtualSize XF86NAME(xf86RandR12GetOriginalVirtualSize)
#define xf86RandR12GetRotation XF86NAME(xf86RandR12GetRotation)
#define xf86RandR12Init XF86NAME(xf86RandR12Init)
#define xf86RandR12PreInit XF86NAME(xf86RandR12PreInit)
#define xf86RandR12SetConfig XF86NAME(xf86RandR12SetConfig)
#define xf86RandR12SetRotations XF86NAME(xf86RandR12SetRotations)
#define xf86SaveScreen XF86NAME(xf86SaveScreen)
#endif /* _XF86RENAME_H_ */

View File

@ -0,0 +1,402 @@
/*
* 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>
#endif
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "xf86.h"
#include "xf86DDC.h"
#include "fb.h"
#include "windowstr.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"
static int
mode_height (DisplayModePtr mode, Rotation rotation)
{
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_180:
return mode->VDisplay;
case RR_Rotate_90:
case RR_Rotate_270:
return mode->HDisplay;
default:
return 0;
}
}
static int
mode_width (DisplayModePtr mode, Rotation rotation)
{
switch (rotation & 0xf) {
case RR_Rotate_0:
case RR_Rotate_180:
return mode->HDisplay;
case RR_Rotate_90:
case RR_Rotate_270:
return mode->VDisplay;
default:
return 0;
}
}
/* borrowed from composite extension, move to Render and publish? */
static VisualPtr
compGetWindowVisual (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
VisualID vid = wVisual (pWin);
int i;
for (i = 0; i < pScreen->numVisuals; i++)
if (pScreen->visuals[i].vid == vid)
return &pScreen->visuals[i];
return 0;
}
static PictFormatPtr
compWindowFormat (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
return PictureMatchVisual (pScreen, pWin->drawable.depth,
compGetWindowVisual (pWin));
}
static void
xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation,
int dest_width, int dest_height)
{
switch (rotation & 0xf) {
default:
case RR_Rotate_0:
*dst = *src;
break;
case RR_Rotate_90:
dst->x1 = src->y1;
dst->y1 = dest_height - src->x2;
dst->x2 = src->y2;
dst->y2 = dest_height - src->x1;
break;
case RR_Rotate_180:
dst->x1 = dest_width - src->x2;
dst->y1 = dest_height - src->y2;
dst->x2 = dest_width - src->x1;
dst->y2 = dest_height - src->y1;
break;
case RR_Rotate_270:
dst->x1 = dest_width - src->y2;
dst->y1 = src->x1;
dst->y2 = src->x2;
dst->x2 = dest_width - src->y1;
break;
}
if (rotation & RR_Reflect_X) {
int x1 = dst->x1;
dst->x1 = dest_width - dst->x2;
dst->x2 = dest_width - x1;
}
if (rotation & RR_Reflect_Y) {
int y1 = dst->y1;
dst->y1 = dest_height - dst->y2;
dst->y2 = dest_height - y1;
}
}
static void
xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
{
ScrnInfoPtr scrn = crtc->scrn;
ScreenPtr screen = scrn->pScreen;
WindowPtr root = WindowTable[screen->myNum];
PixmapPtr dst_pixmap = crtc->rotatedPixmap;
PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]);
int error;
PicturePtr src, dst;
PictTransform transform;
int n = REGION_NUM_RECTS(region);
BoxPtr b = REGION_RECTS(region);
XID include_inferiors = IncludeInferiors;
src = CreatePicture (None,
&root->drawable,
format,
CPSubwindowMode,
&include_inferiors,
serverClient,
&error);
if (!src) {
ErrorF("couldn't create src pict\n");
return;
}
dst = CreatePicture (None,
&dst_pixmap->drawable,
format,
0L,
NULL,
serverClient,
&error);
if (!dst) {
ErrorF("couldn't create src pict\n");
return;
}
memset (&transform, '\0', sizeof (transform));
transform.matrix[2][2] = IntToxFixed(1);
transform.matrix[0][2] = IntToxFixed(crtc->x);
transform.matrix[1][2] = IntToxFixed(crtc->y);
switch (crtc->rotation & 0xf) {
default:
case RR_Rotate_0:
transform.matrix[0][0] = IntToxFixed(1);
transform.matrix[1][1] = IntToxFixed(1);
break;
case RR_Rotate_90:
transform.matrix[0][1] = IntToxFixed(-1);
transform.matrix[1][0] = IntToxFixed(1);
transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
break;
case RR_Rotate_180:
transform.matrix[0][0] = IntToxFixed(-1);
transform.matrix[1][1] = IntToxFixed(-1);
transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
break;
case RR_Rotate_270:
transform.matrix[0][1] = IntToxFixed(1);
transform.matrix[1][0] = IntToxFixed(-1);
transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
break;
}
/* handle reflection */
if (crtc->rotation & RR_Reflect_X)
{
/* XXX figure this out */
}
if (crtc->rotation & RR_Reflect_Y)
{
/* XXX figure this out too */
}
error = SetPictureTransform (src, &transform);
if (error) {
ErrorF("Couldn't set transform\n");
return;
}
while (n--)
{
BoxRec dst_box;
xf86RotateBox (&dst_box, b, crtc->rotation,
crtc->mode.HDisplay, crtc->mode.VDisplay);
CompositePicture (PictOpSrc,
src, NULL, dst,
dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
dst_box.x2 - dst_box.x1,
dst_box.y2 - dst_box.y1);
b++;
}
FreePicture (src, None);
FreePicture (dst, None);
}
static void
xf86RotateRedisplay(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
DamagePtr damage = xf86_config->rotationDamage;
RegionPtr region;
if (!damage)
return;
region = DamageRegion(damage);
if (REGION_NOTEMPTY(pScreen, region))
{
int c;
for (c = 0; c < xf86_config->num_crtc; c++)
{
xf86CrtcPtr crtc = xf86_config->crtc[c];
if (crtc->rotation != RR_Rotate_0)
{
BoxRec box;
RegionRec crtc_damage;
/* compute portion of damage that overlaps crtc */
box.x1 = crtc->x;
box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation);
box.y1 = crtc->y;
box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation);
REGION_INIT(pScreen, &crtc_damage, &box, 1);
REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
/* update damaged region */
if (REGION_NOTEMPTY(pScreen, &crtc_damage))
xf86RotateCrtcRedisplay (crtc, &crtc_damage);
REGION_UNINIT (pScreen, &crtc_damage);
}
}
DamageEmpty(damage);
}
}
static void
xf86RotateBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
{
ScreenPtr pScreen = (ScreenPtr) data;
xf86RotateRedisplay(pScreen);
}
static void
xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask)
{
}
Bool
xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
{
ScrnInfoPtr pScrn = crtc->scrn;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
if (rotation == RR_Rotate_0)
{
/* Free memory from rotation */
if (crtc->rotatedPixmap)
{
crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap);
crtc->rotatedPixmap = NULL;
}
if (xf86_config->rotationDamage)
{
/* Free damage structure */
DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
xf86_config->rotationDamage);
DamageDestroy (xf86_config->rotationDamage);
xf86_config->rotationDamage = NULL;
/* Free block/wakeup handler */
RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
xf86RotateWakeupHandler,
(pointer) pScreen);
}
}
else
{
/*
* these are the size of the shadow pixmap, which
* matches the mode, not the pre-rotated copy in the
* frame buffer
*/
int width = mode->HDisplay;
int height = mode->VDisplay;
PixmapPtr shadow = crtc->rotatedPixmap;
int old_width = shadow ? shadow->drawable.width : 0;
int old_height = shadow ? shadow->drawable.height : 0;
BoxRec damage_box;
RegionRec damage_region;
/* Allocate memory for rotation */
if (old_width != width || old_height != height)
{
if (shadow)
{
crtc->funcs->shadow_destroy (crtc, shadow);
crtc->rotatedPixmap = NULL;
}
shadow = crtc->funcs->shadow_create (crtc, width, height);
if (!shadow)
goto bail1;
crtc->rotatedPixmap = shadow;
}
if (!xf86_config->rotationDamage)
{
/* Create damage structure */
xf86_config->rotationDamage = DamageCreate (NULL, NULL,
DamageReportNone,
TRUE, pScreen, pScreen);
if (!xf86_config->rotationDamage)
goto bail2;
/* Hook damage to screen pixmap */
DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
xf86_config->rotationDamage);
/* Assign block/wakeup handler */
if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
xf86RotateWakeupHandler,
(pointer) pScreen))
{
goto bail3;
}
damage_box.x1 = 0;
damage_box.y1 = 0;
damage_box.x2 = mode_width (mode, rotation);
damage_box.y2 = mode_height (mode, rotation);
REGION_INIT (pScreen, &damage_region, &damage_box, 1);
DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
&damage_region);
REGION_UNINIT (pScreen, &damage_region);
}
if (0)
{
bail3:
DamageDestroy (xf86_config->rotationDamage);
xf86_config->rotationDamage = NULL;
bail2:
if (shadow)
{
crtc->funcs->shadow_destroy (crtc, shadow);
crtc->rotatedPixmap = NULL;
}
bail1:
if (old_width && old_height)
crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
old_width,
old_height);
return FALSE;
}
}
/* All done */
return TRUE;
}

303
hw/xfree86/modes/xf86cvt.c Normal file
View File

@ -0,0 +1,303 @@
/*
* Copyright 2005-2006 Luc Verhaegen.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file This is a copy of xf86cvt.c from the X Server, for compatibility with
* old servers (pre-1.2).
*/
/*
* The reason for having this function in a file of its own is
* so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
* code is shared directly.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xf86.h"
#include <string.h>
/*
* Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
*
* These calculations are stolen from the CVT calculation spreadsheet written
* by Graham Loveridge. He seems to be claiming no copyright and there seems to
* be no license attached to this. He apparently just wants to see his name
* mentioned.
*
* This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
*
* Comments and structure corresponds to the comments and structure of the xls.
* This should ease importing of future changes to the standard (not very
* likely though).
*
* About margins; i'm sure that they are to be the bit between HDisplay and
* HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
* VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
* outside sync "margin" for some reason. Since we prefer seeing proper
* blanking instead of the overscan colour, and since the Crtc* values will
* probably get altered after us, we will disable margins altogether. With
* these calculations, Margins will plainly expand H/VDisplay, and we don't
* want that. -- libv
*
*/
_X_EXPORT DisplayModePtr
xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
Bool Interlaced)
{
DisplayModeRec *Mode = xnfalloc(sizeof(DisplayModeRec));
/* 1) top/bottom margin size (% of height) - default: 1.8 */
#define CVT_MARGIN_PERCENTAGE 1.8
/* 2) character cell horizontal granularity (pixels) - default 8 */
#define CVT_H_GRANULARITY 8
/* 4) Minimum vertical porch (lines) - default 3 */
#define CVT_MIN_V_PORCH 3
/* 4) Minimum number of vertical back porch lines - default 6 */
#define CVT_MIN_V_BPORCH 6
/* Pixel Clock step (kHz) */
#define CVT_CLOCK_STEP 250
Bool Margins = FALSE;
float VFieldRate, HPeriod;
int HDisplayRnd, HMargin;
int VDisplayRnd, VMargin, VSync;
float Interlace; /* Please rename this */
memset(Mode, 0, sizeof(DisplayModeRec));
/* CVT default is 60.0Hz */
if (!VRefresh)
VRefresh = 60.0;
/* 1. Required field rate */
if (Interlaced)
VFieldRate = VRefresh * 2;
else
VFieldRate = VRefresh;
/* 2. Horizontal pixels */
HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
/* 3. Determine left and right borders */
if (Margins) {
/* right margin is actually exactly the same as left */
HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
HMargin -= HMargin % CVT_H_GRANULARITY;
} else
HMargin = 0;
/* 4. Find total active pixels */
Mode->HDisplay = HDisplayRnd + 2*HMargin;
/* 5. Find number of lines per field */
if (Interlaced)
VDisplayRnd = VDisplay / 2;
else
VDisplayRnd = VDisplay;
/* 6. Find top and bottom margins */
/* nope. */
if (Margins)
/* top and bottom margins are equal again. */
VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
else
VMargin = 0;
Mode->VDisplay = VDisplay + 2*VMargin;
/* 7. Interlace */
if (Interlaced)
Interlace = 0.5;
else
Interlace = 0.0;
/* Determine VSync Width from aspect ratio */
if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
VSync = 4;
else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
VSync = 5;
else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
VSync = 6;
else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
VSync = 7;
else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
VSync = 7;
else /* Custom */
VSync = 10;
if (!Reduced) { /* simplified GTF calculation */
/* 4) Minimum time of vertical sync + back porch interval (µs)
* default 550.0 */
#define CVT_MIN_VSYNC_BP 550.0
/* 3) Nominal HSync width (% of line period) - default 8 */
#define CVT_HSYNC_PERCENTAGE 8
float HBlankPercentage;
int VSyncAndBackPorch, VBackPorch;
int HBlank;
/* 8. Estimated Horizontal period */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
(VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
/* 9. Find number of lines in sync + backporch */
if (((int)(CVT_MIN_VSYNC_BP / HPeriod) + 1) < (VSync + CVT_MIN_V_PORCH))
VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
else
VSyncAndBackPorch = (int)(CVT_MIN_VSYNC_BP / HPeriod) + 1;
/* 10. Find number of lines in back porch */
VBackPorch = VSyncAndBackPorch - VSync;
/* 11. Find total number of lines in vertical field */
Mode->VTotal = VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace
+ CVT_MIN_V_PORCH;
/* 5) Definition of Horizontal blanking time limitation */
/* Gradient (%/kHz) - default 600 */
#define CVT_M_FACTOR 600
/* Offset (%) - default 40 */
#define CVT_C_FACTOR 40
/* Blanking time scaling factor - default 128 */
#define CVT_K_FACTOR 128
/* Scaling factor weighting - default 20 */
#define CVT_J_FACTOR 20
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
CVT_J_FACTOR
/* 12. Find ideal blanking duty cycle from formula */
HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod/1000.0;
/* 13. Blanking time */
if (HBlankPercentage < 20)
HBlankPercentage = 20;
HBlank = Mode->HDisplay * HBlankPercentage/(100.0 - HBlankPercentage);
HBlank -= HBlank % (2*CVT_H_GRANULARITY);
/* 14. Find total number of pixels in a line. */
Mode->HTotal = Mode->HDisplay + HBlank;
/* Fill in HSync values */
Mode->HSyncEnd = Mode->HDisplay + HBlank / 2;
Mode->HSyncStart = Mode->HSyncEnd -
(Mode->HTotal * CVT_HSYNC_PERCENTAGE) / 100;
Mode->HSyncStart += CVT_H_GRANULARITY -
Mode->HSyncStart % CVT_H_GRANULARITY;
/* Fill in VSync values */
Mode->VSyncStart = Mode->VDisplay + CVT_MIN_V_PORCH;
Mode->VSyncEnd = Mode->VSyncStart + VSync;
} else { /* Reduced blanking */
/* Minimum vertical blanking interval time (µs) - default 460 */
#define CVT_RB_MIN_VBLANK 460.0
/* Fixed number of clocks for horizontal sync */
#define CVT_RB_H_SYNC 32.0
/* Fixed number of clocks for horizontal blanking */
#define CVT_RB_H_BLANK 160.0
/* Fixed number of lines for vertical front porch - default 3 */
#define CVT_RB_VFPORCH 3
int VBILines;
/* 8. Estimate Horizontal period. */
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
(VDisplayRnd + 2*VMargin);
/* 9. Find number of lines in vertical blanking */
VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
/* 10. Check if vertical blanking is sufficient */
if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
/* 11. Find total number of lines in vertical field */
Mode->VTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
/* 12. Find total number of pixels in a line */
Mode->HTotal = Mode->HDisplay + CVT_RB_H_BLANK;
/* Fill in HSync values */
Mode->HSyncEnd = Mode->HDisplay + CVT_RB_H_BLANK / 2;
Mode->HSyncStart = Mode->HSyncEnd - CVT_RB_H_SYNC;
/* Fill in VSync values */
Mode->VSyncStart = Mode->VDisplay + CVT_RB_VFPORCH;
Mode->VSyncEnd = Mode->VSyncStart + VSync;
}
/* 15/13. Find pixel clock frequency (kHz for xf86) */
Mode->Clock = Mode->HTotal * 1000.0 / HPeriod;
Mode->Clock -= Mode->Clock % CVT_CLOCK_STEP;
/* 16/14. Find actual Horizontal Frequency (kHz) */
Mode->HSync = ((float) Mode->Clock) / ((float) Mode->HTotal);
/* 17/15. Find actual Field rate */
Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
((float) (Mode->HTotal * Mode->VTotal));
/* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */
if (Interlaced)
Mode->VTotal *= 2;
{
char Name[256];
Name[0] = 0;
snprintf(Name, 256, "%dx%d", HDisplay, VDisplay);
Mode->name = xnfalloc(strlen(Name) + 1);
memcpy(Mode->name, Name, strlen(Name) + 1);
}
if (Reduced)
Mode->Flags |= V_PHSYNC | V_NVSYNC;
else
Mode->Flags |= V_NHSYNC | V_PVSYNC;
if (Interlaced)
Mode->Flags |= V_INTERLACE;
return Mode;
}

View File

@ -199,10 +199,11 @@ xf86CursorEnableDisableFBAccess(
pScreen->devPrivates[xf86CursorScreenIndex].ptr;
if (!enable && ScreenPriv->CurrentCursor != NullCursor) {
ScreenPriv->SavedCursor = ScreenPriv->CurrentCursor;
CursorPtr currentCursor = ScreenPriv->CurrentCursor;
xf86CursorSetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y);
ScreenPriv->isUp = FALSE;
ScreenPriv->SWCursor = TRUE;
ScreenPriv->SavedCursor = currentCursor;
}
if (ScreenPriv->EnableDisableFBAccess)