xserver-multidpi/hw/xfree86/common/xf86Mode.c

2123 lines
72 KiB
C
Raw Normal View History

2003-11-14 17:48:57 +01:00
/*
* 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.
2003-11-14 17:48:57 +01:00
*
* 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).
*/
/*
* LCM() and scanLineWidth() are:
*
* Copyright 1997 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
*
* 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 Marc Aurele La France not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Marc Aurele La France makes no representations
* about the suitability of this software for any purpose. It is provided
* "as-is" without express or implied warranty.
*
* MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL MARC AURELE LA FRANCE 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.
*
* Copyright 1990,91,92,93 by Thomas Roell, Germany.
* Copyright 1991,92,93 by SGCS (Snitily Graphics Consulting Services), USA.
*
* 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 Thomas Roell nor
* SGCS be used in advertising or publicity pertaining to distribution
* of the software without specific, written prior permission.
* Thomas Roell nor SGCS makes no representations about the suitability
* of this software for any purpose. It is provided "as is" without
* express or implied warranty.
*
* THOMAS ROELL AND SGCS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL THOMAS ROELL OR SGCS 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.
*/
/*
2003-11-14 17:48:57 +01:00
* Authors: Dirk Hohndel <hohndel@XFree86.Org>
* David Dawes <dawes@XFree86.Org>
* Marc La France <tsi@XFree86.Org>
* ... and others
2003-11-14 17:48:57 +01:00
*
* This file includes helper functions for mode related things.
*/
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include <X11/X.h>
#include "xf86Modes.h"
#include "xf86Crtc.h"
#include "os.h"
2003-11-14 17:48:57 +01:00
#include "servermd.h"
#include "globals.h"
2003-11-14 17:48:57 +01:00
#include "xf86.h"
#include "xf86Priv.h"
#include "edid.h"
2003-11-14 17:48:57 +01:00
static void
printModeRejectMessage(int index, DisplayModePtr p, int status)
{
const char *type;
if (p->type & M_T_BUILTIN)
type = "built-in ";
else if (p->type & M_T_DEFAULT)
type = "default ";
else if (p->type & M_T_DRIVER)
type = "driver ";
else
type = "";
xf86DrvMsg(index, X_INFO, "Not using %smode \"%s\" (%s)\n", type, p->name,
xf86ModeStatusToString(status));
}
2003-11-14 17:48:57 +01:00
/*
* Find closest clock to given frequency (in kHz). This assumes the
* number of clocks is greater than zero.
2003-11-14 17:48:57 +01:00
*/
static int
2003-11-14 17:48:57 +01:00
xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2,
int DivFactor, int MulFactor, int *divider)
2003-11-14 17:48:57 +01:00
{
int nearestClock = 0, nearestDiv = 1;
int minimumGap = abs(freq - scrp->clock[0]);
int i, j, k, gap;
if (allowDiv2)
k = 2;
2003-11-14 17:48:57 +01:00
else
k = 1;
2003-11-14 17:48:57 +01:00
/* Must set this here in case the best match is scrp->clock[0] */
if (divider != NULL)
*divider = 0;
for (i = 0; i < scrp->numClocks; i++) {
for (j = 1; j <= k; j++) {
gap = abs((freq * j) - ((scrp->clock[i] * DivFactor) / MulFactor));
if ((gap < minimumGap) || ((gap == minimumGap) && (j < nearestDiv))) {
minimumGap = gap;
nearestClock = i;
nearestDiv = j;
if (divider != NULL)
*divider = (j - 1) * V_CLKDIV2;
}
}
2003-11-14 17:48:57 +01:00
}
return nearestClock;
}
/*
* xf86ModeStatusToString
*
* Convert a ModeStatus value to a printable message
*/
const char *
2003-11-14 17:48:57 +01:00
xf86ModeStatusToString(ModeStatus status)
{
switch (status) {
case MODE_OK:
return "Mode OK";
2003-11-14 17:48:57 +01:00
case MODE_HSYNC:
return "hsync out of range";
2003-11-14 17:48:57 +01:00
case MODE_VSYNC:
return "vrefresh out of range";
2003-11-14 17:48:57 +01:00
case MODE_H_ILLEGAL:
return "illegal horizontal timings";
2003-11-14 17:48:57 +01:00
case MODE_V_ILLEGAL:
return "illegal vertical timings";
2003-11-14 17:48:57 +01:00
case MODE_BAD_WIDTH:
return "width requires unsupported line pitch";
2003-11-14 17:48:57 +01:00
case MODE_NOMODE:
return "no mode of this name";
2003-11-14 17:48:57 +01:00
case MODE_NO_INTERLACE:
return "interlace mode not supported";
2003-11-14 17:48:57 +01:00
case MODE_NO_DBLESCAN:
return "doublescan mode not supported";
2003-11-14 17:48:57 +01:00
case MODE_NO_VSCAN:
return "multiscan mode not supported";
2003-11-14 17:48:57 +01:00
case MODE_MEM:
return "insufficient memory for mode";
2003-11-14 17:48:57 +01:00
case MODE_VIRTUAL_X:
return "width too large for virtual size";
2003-11-14 17:48:57 +01:00
case MODE_VIRTUAL_Y:
return "height too large for virtual size";
2003-11-14 17:48:57 +01:00
case MODE_MEM_VIRT:
return "insufficient memory given virtual size";
2003-11-14 17:48:57 +01:00
case MODE_NOCLOCK:
return "no clock available for mode";
2003-11-14 17:48:57 +01:00
case MODE_CLOCK_HIGH:
return "mode clock too high";
2003-11-14 17:48:57 +01:00
case MODE_CLOCK_LOW:
return "mode clock too low";
2003-11-14 17:48:57 +01:00
case MODE_CLOCK_RANGE:
return "bad mode clock/interlace/doublescan";
2003-11-14 17:48:57 +01:00
case MODE_BAD_HVALUE:
return "horizontal timing out of range";
2003-11-14 17:48:57 +01:00
case MODE_BAD_VVALUE:
return "vertical timing out of range";
2003-11-14 17:48:57 +01:00
case MODE_BAD_VSCAN:
return "VScan value out of range";
2003-11-14 17:48:57 +01:00
case MODE_HSYNC_NARROW:
return "horizontal sync too narrow";
2003-11-14 17:48:57 +01:00
case MODE_HSYNC_WIDE:
return "horizontal sync too wide";
2003-11-14 17:48:57 +01:00
case MODE_HBLANK_NARROW:
return "horizontal blanking too narrow";
2003-11-14 17:48:57 +01:00
case MODE_HBLANK_WIDE:
return "horizontal blanking too wide";
2003-11-14 17:48:57 +01:00
case MODE_VSYNC_NARROW:
return "vertical sync too narrow";
2003-11-14 17:48:57 +01:00
case MODE_VSYNC_WIDE:
return "vertical sync too wide";
2003-11-14 17:48:57 +01:00
case MODE_VBLANK_NARROW:
return "vertical blanking too narrow";
2003-11-14 17:48:57 +01:00
case MODE_VBLANK_WIDE:
return "vertical blanking too wide";
2003-11-14 17:48:57 +01:00
case MODE_PANEL:
return "exceeds panel dimensions";
2003-11-14 17:48:57 +01:00
case MODE_INTERLACE_WIDTH:
return "width too large for interlaced mode";
2003-11-14 17:48:57 +01:00
case MODE_ONE_WIDTH:
return "all modes must have the same width";
case MODE_ONE_HEIGHT:
return "all modes must have the same height";
case MODE_ONE_SIZE:
return "all modes must have the same resolution";
case MODE_NO_REDUCED:
return "monitor doesn't support reduced blanking";
case MODE_BANDWIDTH:
return "mode requires too much memory bandwidth";
2003-11-14 17:48:57 +01:00
case MODE_BAD:
return "unknown reason";
2003-11-14 17:48:57 +01:00
case MODE_ERROR:
return "internal error";
2003-11-14 17:48:57 +01:00
default:
return "unknown";
2003-11-14 17:48:57 +01:00
}
}
/*
* xf86ShowClockRanges() -- Print the clock ranges allowed
* and the clock values scaled by ClockMulFactor and ClockDivFactor
*/
void
2003-11-14 17:48:57 +01:00
xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges)
{
ClockRangePtr cp;
int MulFactor = 1;
int DivFactor = 1;
int i, j;
int scaledClock;
for (cp = clockRanges; cp != NULL; cp = cp->next) {
DivFactor = max(1, cp->ClockDivFactor);
MulFactor = max(1, cp->ClockMulFactor);
if (scrp->progClock) {
if (cp->minClock) {
if (cp->maxClock) {
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"Clock range: %6.2f to %6.2f MHz\n",
(double) cp->minClock / 1000.0,
(double) cp->maxClock / 1000.0);
}
else {
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"Minimum clock: %6.2f MHz\n",
(double) cp->minClock / 1000.0);
}
}
else {
if (cp->maxClock) {
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"Maximum clock: %6.2f MHz\n",
(double) cp->maxClock / 1000.0);
}
}
}
else if (DivFactor > 1 || MulFactor > 1) {
j = 0;
for (i = 0; i < scrp->numClocks; i++) {
scaledClock = (scrp->clock[i] * DivFactor) / MulFactor;
if (scaledClock >= cp->minClock && scaledClock <= cp->maxClock) {
if ((j % 8) == 0) {
if (j > 0)
xf86ErrorF("\n");
xf86DrvMsg(scrp->scrnIndex, X_INFO, "scaled clocks:");
}
xf86ErrorF(" %6.2f", (double) scaledClock / 1000.0);
j++;
}
}
xf86ErrorF("\n");
}
2003-11-14 17:48:57 +01:00
}
}
static Bool
modeInClockRange(ClockRangePtr cp, DisplayModePtr p)
{
return ((p->Clock >= cp->minClock) &&
(p->Clock <= cp->maxClock) &&
(cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) &&
(cp->doubleScanAllowed ||
((p->VScan <= 1) && !(p->Flags & V_DBLSCAN))));
}
2003-11-14 17:48:57 +01:00
/*
* xf86FindClockRangeForMode() [... like the name says ...]
*/
static ClockRangePtr
xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p)
{
ClockRangePtr cp;
for (cp = clockRanges;; cp = cp->next)
if (!cp || modeInClockRange(cp, p))
return cp;
2003-11-14 17:48:57 +01:00
}
/*
* xf86HandleBuiltinMode() - handles built-in modes
*/
static ModeStatus
xf86HandleBuiltinMode(ScrnInfoPtr scrp,
DisplayModePtr p,
DisplayModePtr modep,
ClockRangePtr clockRanges, Bool allowDiv2)
2003-11-14 17:48:57 +01:00
{
ClockRangePtr cp;
int extraFlags = 0;
int MulFactor = 1;
int DivFactor = 1;
int clockIndex;
2003-11-14 17:48:57 +01:00
/* Reject previously rejected modes */
if (p->status != MODE_OK)
return p->status;
2003-11-14 17:48:57 +01:00
/* Reject previously considered modes */
if (p->prev)
return MODE_NOMODE;
if ((p->type & M_T_CLOCK_C) == M_T_CLOCK_C) {
/* Check clock is in range */
cp = xf86FindClockRangeForMode(clockRanges, p);
if (cp == NULL) {
modep->type = p->type;
p->status = MODE_CLOCK_RANGE;
return MODE_CLOCK_RANGE;
}
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
if (!scrp->progClock) {
clockIndex = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
cp->ClockDivFactor,
cp->ClockMulFactor, &extraFlags);
modep->Clock = (scrp->clock[clockIndex] * DivFactor)
/ MulFactor;
modep->ClockIndex = clockIndex;
modep->SynthClock = scrp->clock[clockIndex];
if (extraFlags & V_CLKDIV2) {
modep->Clock /= 2;
modep->SynthClock /= 2;
}
}
else {
2003-11-14 17:48:57 +01:00
modep->Clock = p->Clock;
modep->ClockIndex = -1;
modep->SynthClock = (modep->Clock * MulFactor)
/ DivFactor;
}
modep->PrivFlags = cp->PrivFlags;
2003-11-14 17:48:57 +01:00
}
else {
if (!scrp->progClock) {
modep->Clock = p->Clock;
modep->ClockIndex = p->ClockIndex;
modep->SynthClock = p->SynthClock;
}
else {
modep->Clock = p->Clock;
modep->ClockIndex = -1;
modep->SynthClock = p->SynthClock;
}
modep->PrivFlags = p->PrivFlags;
}
modep->type = p->type;
modep->HDisplay = p->HDisplay;
modep->HSyncStart = p->HSyncStart;
modep->HSyncEnd = p->HSyncEnd;
modep->HTotal = p->HTotal;
modep->HSkew = p->HSkew;
modep->VDisplay = p->VDisplay;
modep->VSyncStart = p->VSyncStart;
modep->VSyncEnd = p->VSyncEnd;
modep->VTotal = p->VTotal;
modep->VScan = p->VScan;
modep->Flags = p->Flags | extraFlags;
modep->CrtcHDisplay = p->CrtcHDisplay;
2003-11-14 17:48:57 +01:00
modep->CrtcHBlankStart = p->CrtcHBlankStart;
modep->CrtcHSyncStart = p->CrtcHSyncStart;
modep->CrtcHSyncEnd = p->CrtcHSyncEnd;
modep->CrtcHBlankEnd = p->CrtcHBlankEnd;
modep->CrtcHTotal = p->CrtcHTotal;
modep->CrtcHSkew = p->CrtcHSkew;
modep->CrtcVDisplay = p->CrtcVDisplay;
2003-11-14 17:48:57 +01:00
modep->CrtcVBlankStart = p->CrtcVBlankStart;
modep->CrtcVSyncStart = p->CrtcVSyncStart;
modep->CrtcVSyncEnd = p->CrtcVSyncEnd;
modep->CrtcVBlankEnd = p->CrtcVBlankEnd;
modep->CrtcVTotal = p->CrtcVTotal;
modep->CrtcHAdjusted = p->CrtcHAdjusted;
modep->CrtcVAdjusted = p->CrtcVAdjusted;
modep->HSync = p->HSync;
modep->VRefresh = p->VRefresh;
modep->Private = p->Private;
modep->PrivSize = p->PrivSize;
2003-11-14 17:48:57 +01:00
p->prev = modep;
2003-11-14 17:48:57 +01:00
return MODE_OK;
}
/*
* xf86LookupMode
*
* This function returns a mode from the given list which matches the
* given name. When multiple modes with the same name are available,
* the method of picking the matching mode is determined by the
* strategy selected.
*
* This function takes the following parameters:
* scrp ScrnInfoPtr
* modep pointer to the returned mode, which must have the name
* field filled in.
* clockRanges a list of clock ranges. This is optional when all the
* modes are built-in modes.
* strategy how to decide which mode to use from multiple modes with
* the same name
*
* In addition, the following fields from the ScrnInfoRec are used:
* modePool the list of monitor modes compatible with the driver
* clocks a list of discrete clocks
* numClocks number of discrete clocks
* progClock clock is programmable
*
* If a mode was found, its values are filled in to the area pointed to
* by modep, If a mode was not found the return value indicates the
* reason.
*/
static ModeStatus
2003-11-14 17:48:57 +01:00
xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep,
ClockRangePtr clockRanges, LookupModeFlags strategy)
2003-11-14 17:48:57 +01:00
{
DisplayModePtr p, bestMode = NULL;
ClockRangePtr cp;
int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1;
double refresh, bestRefresh = 0.0;
Bool found = FALSE;
int extraFlags = 0;
int clockIndex = -1;
int MulFactor = 1;
int DivFactor = 1;
int ModePrivFlags = 0;
ModeStatus status = MODE_NOMODE;
Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0;
int n;
const int types[] = {
M_T_BUILTIN | M_T_PREFERRED,
M_T_BUILTIN,
M_T_USERDEF | M_T_PREFERRED,
M_T_USERDEF,
M_T_DRIVER | M_T_PREFERRED,
M_T_DRIVER,
0
};
const int ntypes = ARRAY_SIZE(types);
2003-11-14 17:48:57 +01:00
strategy &= ~(LOOKUP_CLKDIV2 | LOOKUP_OPTIONAL_TOLERANCES);
/* Some sanity checking */
if (scrp == NULL || scrp->modePool == NULL ||
(!scrp->progClock && scrp->numClocks == 0)) {
ErrorF("xf86LookupMode: called with invalid scrnInfoRec\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
if (modep == NULL || modep->name == NULL) {
ErrorF("xf86LookupMode: called with invalid modep\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
for (cp = clockRanges; cp != NULL; cp = cp->next) {
/* DivFactor and MulFactor must be > 0 */
cp->ClockDivFactor = max(1, cp->ClockDivFactor);
cp->ClockMulFactor = max(1, cp->ClockMulFactor);
2003-11-14 17:48:57 +01:00
}
/* Scan the mode pool for matching names */
for (n = 0; n < ntypes; n++) {
int type = types[n];
for (p = scrp->modePool; p != NULL; p = p->next) {
/* scan through the modes in the sort order above */
if ((p->type & type) != type)
continue;
if (strcmp(p->name, modep->name) == 0) {
/* Skip over previously rejected modes */
if (p->status != MODE_OK) {
if (!found)
status = p->status;
continue;
}
/* Skip over previously considered modes */
if (p->prev)
continue;
if (p->type & M_T_BUILTIN) {
return xf86HandleBuiltinMode(scrp, p, modep, clockRanges,
allowDiv2);
}
/* Check clock is in range */
cp = xf86FindClockRangeForMode(clockRanges, p);
if (cp == NULL) {
/*
* XXX Could do more here to provide a more detailed
* reason for not finding a mode.
*/
p->status = MODE_CLOCK_RANGE;
if (!found)
status = MODE_CLOCK_RANGE;
continue;
}
/*
* If programmable clock and strategy is not
* LOOKUP_BEST_REFRESH, the required mode has been found,
* otherwise record the refresh and continue looking.
*/
if (scrp->progClock) {
found = TRUE;
if (strategy != LOOKUP_BEST_REFRESH) {
bestMode = p;
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
break;
}
refresh = xf86ModeVRefresh(p);
if (p->Flags & V_INTERLACE)
refresh /= INTERLACE_REFRESH_WEIGHT;
if (refresh > bestRefresh) {
bestMode = p;
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
bestRefresh = refresh;
}
continue;
}
/*
* Clock is in range, so if it is not a programmable clock, find
* a matching clock.
*/
i = xf86GetNearestClock(scrp, p->Clock, allowDiv2,
cp->ClockDivFactor, cp->ClockMulFactor,
&k);
/*
* If the clock is too far from the requested clock, this
* mode is no good.
*/
if (k & V_CLKDIV2)
gap = abs((p->Clock * 2) -
((scrp->clock[i] * cp->ClockDivFactor) /
cp->ClockMulFactor));
else
gap = abs(p->Clock -
((scrp->clock[i] * cp->ClockDivFactor) /
cp->ClockMulFactor));
if (gap > minimumGap) {
p->status = MODE_NOCLOCK;
if (!found)
status = MODE_NOCLOCK;
continue;
}
found = TRUE;
if (strategy == LOOKUP_BEST_REFRESH) {
refresh = xf86ModeVRefresh(p);
if (p->Flags & V_INTERLACE)
refresh /= INTERLACE_REFRESH_WEIGHT;
if (refresh > bestRefresh) {
bestMode = p;
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
extraFlags = k;
clockIndex = i;
bestRefresh = refresh;
}
continue;
}
if (strategy == LOOKUP_CLOSEST_CLOCK) {
if (gap < minimumGap) {
bestMode = p;
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
extraFlags = k;
clockIndex = i;
minimumGap = gap;
}
continue;
}
/*
* If strategy is neither LOOKUP_BEST_REFRESH or
* LOOKUP_CLOSEST_CLOCK the required mode has been found.
*/
bestMode = p;
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
extraFlags = k;
clockIndex = i;
break;
}
}
if (found)
break;
2003-11-14 17:48:57 +01:00
}
if (!found || bestMode == NULL)
return status;
2003-11-14 17:48:57 +01:00
/* Fill in the mode parameters */
if (scrp->progClock) {
modep->Clock = bestMode->Clock;
modep->ClockIndex = -1;
modep->SynthClock = (modep->Clock * MulFactor) / DivFactor;
}
else {
modep->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor;
modep->ClockIndex = clockIndex;
modep->SynthClock = scrp->clock[clockIndex];
if (extraFlags & V_CLKDIV2) {
modep->Clock /= 2;
modep->SynthClock /= 2;
}
2003-11-14 17:48:57 +01:00
}
modep->type = bestMode->type;
modep->PrivFlags = ModePrivFlags;
modep->HDisplay = bestMode->HDisplay;
modep->HSyncStart = bestMode->HSyncStart;
modep->HSyncEnd = bestMode->HSyncEnd;
modep->HTotal = bestMode->HTotal;
modep->HSkew = bestMode->HSkew;
modep->VDisplay = bestMode->VDisplay;
modep->VSyncStart = bestMode->VSyncStart;
modep->VSyncEnd = bestMode->VSyncEnd;
modep->VTotal = bestMode->VTotal;
modep->VScan = bestMode->VScan;
modep->Flags = bestMode->Flags | extraFlags;
modep->CrtcHDisplay = bestMode->CrtcHDisplay;
modep->CrtcHBlankStart = bestMode->CrtcHBlankStart;
modep->CrtcHSyncStart = bestMode->CrtcHSyncStart;
modep->CrtcHSyncEnd = bestMode->CrtcHSyncEnd;
modep->CrtcHBlankEnd = bestMode->CrtcHBlankEnd;
modep->CrtcHTotal = bestMode->CrtcHTotal;
modep->CrtcHSkew = bestMode->CrtcHSkew;
modep->CrtcVDisplay = bestMode->CrtcVDisplay;
modep->CrtcVBlankStart = bestMode->CrtcVBlankStart;
modep->CrtcVSyncStart = bestMode->CrtcVSyncStart;
modep->CrtcVSyncEnd = bestMode->CrtcVSyncEnd;
modep->CrtcVBlankEnd = bestMode->CrtcVBlankEnd;
modep->CrtcVTotal = bestMode->CrtcVTotal;
modep->CrtcHAdjusted = bestMode->CrtcHAdjusted;
modep->CrtcVAdjusted = bestMode->CrtcVAdjusted;
modep->HSync = bestMode->HSync;
modep->VRefresh = bestMode->VRefresh;
modep->Private = bestMode->Private;
modep->PrivSize = bestMode->PrivSize;
2003-11-14 17:48:57 +01:00
bestMode->prev = modep;
return MODE_OK;
}
/*
* xf86CheckModeForMonitor
*
* This function takes a mode and monitor description, and determines
* if the mode is valid for the monitor.
*/
ModeStatus
2003-11-14 17:48:57 +01:00
xf86CheckModeForMonitor(DisplayModePtr mode, MonPtr monitor)
{
int i;
/* Sanity checks */
if (mode == NULL || monitor == NULL) {
ErrorF("xf86CheckModeForMonitor: called with invalid parameters\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
DebugF("xf86CheckModeForMonitor(%p %s, %p %s)\n",
mode, mode->name, monitor, monitor->id);
2003-11-14 17:48:57 +01:00
/* Some basic mode validity checks */
if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart ||
mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal)
return MODE_H_ILLEGAL;
2003-11-14 17:48:57 +01:00
if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart ||
mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal)
return MODE_V_ILLEGAL;
2003-11-14 17:48:57 +01:00
if (monitor->nHsync > 0) {
/* Check hsync against the allowed ranges */
float hsync = xf86ModeHSync(mode);
for (i = 0; i < monitor->nHsync; i++)
if ((hsync > monitor->hsync[i].lo * (1.0 - SYNC_TOLERANCE)) &&
(hsync < monitor->hsync[i].hi * (1.0 + SYNC_TOLERANCE)))
break;
/* Now see whether we ran out of sync ranges without finding a match */
if (i == monitor->nHsync)
return MODE_HSYNC;
2003-11-14 17:48:57 +01:00
}
if (monitor->nVrefresh > 0) {
/* Check vrefresh against the allowed ranges */
float vrefrsh = xf86ModeVRefresh(mode);
for (i = 0; i < monitor->nVrefresh; i++)
if ((vrefrsh > monitor->vrefresh[i].lo * (1.0 - SYNC_TOLERANCE)) &&
(vrefrsh < monitor->vrefresh[i].hi * (1.0 + SYNC_TOLERANCE)))
break;
/* Now see whether we ran out of refresh ranges without finding a match */
if (i == monitor->nVrefresh)
return MODE_VSYNC;
2003-11-14 17:48:57 +01:00
}
/* Force interlaced modes to have an odd VTotal */
if (mode->Flags & V_INTERLACE)
mode->CrtcVTotal = mode->VTotal |= 1;
2003-11-14 17:48:57 +01:00
/*
* This code stops cvt -r modes, and only cvt -r modes, from hitting 15y+
* old CRTs which might, when there is a lot of solar flare activity and
* when the celestial bodies are unfavourably aligned, implode trying to
* sync to it. It's called "Protecting the user from doing anything stupid".
* -- libv
*/
if (xf86ModeIsReduced(mode)) {
if (!monitor->reducedblanking && !(mode->type & M_T_DRIVER))
return MODE_NO_REDUCED;
}
if ((monitor->maxPixClock) && (mode->Clock > monitor->maxPixClock))
return MODE_CLOCK_HIGH;
2003-11-14 17:48:57 +01:00
return MODE_OK;
}
/*
* xf86CheckModeSize
*
* An internal routine to check if a mode fits in video memory. This tries to
* avoid overflows that would otherwise occur when video memory size is greater
* than 256MB.
*/
static Bool
xf86CheckModeSize(ScrnInfoPtr scrp, int w, int x, int y)
{
int bpp = scrp->fbFormat.bitsPerPixel, pad = scrp->fbFormat.scanlinePad;
2003-11-14 17:48:57 +01:00
int lineWidth, lastWidth;
if (scrp->depth == 4)
pad *= 4; /* 4 planes */
2003-11-14 17:48:57 +01:00
/* Sanity check */
if ((w < 0) || (x < 0) || (y <= 0))
return FALSE;
2003-11-14 17:48:57 +01:00
lineWidth = (((w * bpp) + pad - 1) / pad) * pad;
lastWidth = x * bpp;
/*
* At this point, we need to compare
*
* (lineWidth * (y - 1)) + lastWidth
2003-11-14 17:48:57 +01:00
*
* against
*
* scrp->videoRam * (1024 * 8)
2003-11-14 17:48:57 +01:00
*
* These are bit quantities. To avoid overflows, do the comparison in
* terms of BITMAP_SCANLINE_PAD units. This assumes BITMAP_SCANLINE_PAD
* is a power of 2. We currently use 32, which limits us to a video
* memory size of 8GB.
*/
lineWidth = (lineWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD;
lastWidth = (lastWidth + (BITMAP_SCANLINE_PAD - 1)) / BITMAP_SCANLINE_PAD;
if ((lineWidth * (y - 1) + lastWidth) >
(scrp->videoRam * ((1024 * 8) / BITMAP_SCANLINE_PAD)))
return FALSE;
2003-11-14 17:48:57 +01:00
return TRUE;
}
/*
* xf86InitialCheckModeForDriver
*
* This function checks if a mode satisfies a driver's initial requirements:
* - mode size fits within the available pixel area (memory)
* - width lies within the range of supported line pitches
* - mode size fits within virtual size (if fixed)
* - horizontal timings are in range
*
* This function takes the following parameters:
* scrp ScrnInfoPtr
* mode mode to check
* maxPitch (optional) maximum line pitch
* virtualX (optional) virtual width requested
* virtualY (optional) virtual height requested
*
* In addition, the following fields from the ScrnInfoRec are used:
* monitor pointer to structure for monitor section
* fbFormat pixel format for the framebuffer
* videoRam video memory size (in kB)
*/
static ModeStatus
2003-11-14 17:48:57 +01:00
xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode,
ClockRangePtr clockRanges,
LookupModeFlags strategy,
int maxPitch, int virtualX, int virtualY)
2003-11-14 17:48:57 +01:00
{
ClockRangePtr cp;
ModeStatus status;
Bool allowDiv2 = (strategy & LOOKUP_CLKDIV2) != 0;
int i, needDiv2;
2003-11-14 17:48:57 +01:00
/* Sanity checks */
if (!scrp || !mode || !clockRanges) {
ErrorF("xf86InitialCheckModeForDriver: "
"called with invalid parameters\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
DebugF("xf86InitialCheckModeForDriver(%p, %p %s, %p, 0x%x, %d, %d, %d)\n",
scrp, mode, mode->name, clockRanges, strategy, maxPitch, virtualX,
virtualY);
2003-11-14 17:48:57 +01:00
/* Some basic mode validity checks */
if (0 >= mode->HDisplay || mode->HDisplay > mode->HSyncStart ||
mode->HSyncStart >= mode->HSyncEnd || mode->HSyncEnd >= mode->HTotal)
return MODE_H_ILLEGAL;
2003-11-14 17:48:57 +01:00
if (0 >= mode->VDisplay || mode->VDisplay > mode->VSyncStart ||
mode->VSyncStart >= mode->VSyncEnd || mode->VSyncEnd >= mode->VTotal)
return MODE_V_ILLEGAL;
2003-11-14 17:48:57 +01:00
if (!xf86CheckModeSize(scrp, mode->HDisplay, mode->HDisplay,
mode->VDisplay))
2003-11-14 17:48:57 +01:00
return MODE_MEM;
if (maxPitch > 0 && mode->HDisplay > maxPitch)
return MODE_BAD_WIDTH;
2003-11-14 17:48:57 +01:00
if (virtualX > 0 && mode->HDisplay > virtualX)
return MODE_VIRTUAL_X;
2003-11-14 17:48:57 +01:00
if (virtualY > 0 && mode->VDisplay > virtualY)
return MODE_VIRTUAL_Y;
2003-11-14 17:48:57 +01:00
/*
* The use of the DisplayModeRec's Crtc* and SynthClock elements below is
* provisional, in that they are later reused by the driver at mode-set
* time. Here, they are temporarily enlisted to contain the mode timings
* as seen by the CRT or panel (rather than the CRTC). The driver's
* ValidMode() is allowed to modify these so it can deal with such things
* as mode stretching and/or centering. The driver should >NOT< modify the
* user-supplied values as these are reported back when mode validation is
* said and done.
*/
/*
* NOTE: We (ab)use the mode->Crtc* values here to store timing
* information for the calculation of Hsync and Vrefresh. Before
* these values are calculated the driver is given the opportunity
* to either set these HSync and VRefresh itself or modify the timing
* values.
* The difference to the final calculation is small but imortand:
* here we pass the flag INTERLACE_HALVE_V regardless if the driver
* sets it or not. This way our calculation of VRefresh has the same
* effect as if we do if (flags & V_INTERLACE) refresh *= 2.0
* This dual use of the mode->Crtc* values will certainly create
* confusion and is bad software design. However since it's part of
* the driver API it's hard to change.
2003-11-14 17:48:57 +01:00
*/
2003-11-14 17:48:57 +01:00
if (scrp->ValidMode) {
xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
cp = xf86FindClockRangeForMode(clockRanges, mode);
if (!cp)
return MODE_CLOCK_RANGE;
if (cp->ClockMulFactor < 1)
cp->ClockMulFactor = 1;
if (cp->ClockDivFactor < 1)
cp->ClockDivFactor = 1;
/*
* XXX The effect of clock dividers and multipliers on the monitor's
* pixel clock needs to be verified.
*/
if (scrp->progClock) {
mode->SynthClock = mode->Clock;
}
else {
i = xf86GetNearestClock(scrp, mode->Clock, allowDiv2,
cp->ClockDivFactor, cp->ClockMulFactor,
&needDiv2);
mode->SynthClock = (scrp->clock[i] * cp->ClockDivFactor) /
cp->ClockMulFactor;
if (needDiv2 & V_CLKDIV2)
mode->SynthClock /= 2;
}
api: rework the X server driver API to avoid global arrays. This is a squash merge containing all the API changes, as well as the video ABI bump. Its been squashed to make bisection easier. Full patch log below: commit b202738bbf0c5a1c1172767119c2c71f1e7f8070 Author: Aaron Plattner <aplattner@nvidia.com> Date: Mon May 14 15:16:11 2012 -0700 xfree86: Bump video ABI to 13.0 The ABI was broken by changes to convert from screen index numbers to ScreenPtr / ScrnInfoPtr in various structures and function signatures. Signed-off-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3d5f7d9f8d408bcad3f83277d255f25d3b0edbf3 Author: Dave Airlie <airlied@redhat.com> Date: Thu May 24 10:56:57 2012 +0100 xf86: xf86ClearEntityListForScreen should take a pScrn When adding GPU screens this make life easier. (also fix comment, as pointed out by Alan) Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Dave Airlie <airlied@redhat.com> commit afee8b5ab4501597ecc1ade34124d7ca227ab055 Author: Dave Airlie <airlied@redhat.com> Date: Thu May 24 07:07:32 2012 +0100 xf86i2c: add pscrn for drivers to use This just adds a pScrn pointer into the struct for the drivers to use instead of scrnIndex. Mostly scrnIndex is used for logging, but some drivers use it to lookup xf86Screens, so let them stash a pScrn instead. Removing the scrnIndex is a bit more involved and I'm not sure its worth the effort. Doing i2c in the X server is legacy code as far as I'm concerned. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit ea5092f1f679691d187f1eee9427e6057beec56e Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 19:25:20 2012 +0100 dix/gc: consolidate GC object creation in one place The standard GC create and scratch GC create were 90% the same really, and I have a need in the future for creating GC objects without the other bits, so wanted to avoid a third copy. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3d91482ea9b4883e64e496f2768168e0ffa21ba1 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 10:24:06 2012 +0100 xf86: add a define to denote the new non-index interfaces are being used This can be used by drivers to provide compatible APIs. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 37c3ae3e6cd4f3dedc72f371096d6743f8f99df3 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 15:09:12 2012 +0100 dix: make Create/Free scratch pixmaps take a ScreenPtr While technically an API/ABI change I doubt anyone uses it, but it helps in splitting screens up. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 75f2062a3fe94f04764ecc7d2ff2fbbeccb9da60 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:57:55 2012 +0100 xf86/xv: remove scrnIndexfrom xf86FindXvOptions. Move this interface to taking an ScrnInfoPtr. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit f80c2374f40ea7b2ee0556e2e76cc07406f3d843 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:53:59 2012 +0100 xf86: make xf86DeleteScreen take a ScrnInfoPtr (v2) stop passing indices into this function. v2: drop flags argument. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 58824e414f35682435f15bfe6c4b656bd90b9235 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:48:09 2012 +0100 xf86: fix xf86IsScreenPrimary interface to take a pScrn (API/ABI) Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 6b4fc1f9d391bcdf7ca288766e49bce60f4635cd Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:18:59 2012 +0100 xserver: convert block/wakeup handlers to passing ScreenPtr (ABI/API) (v2) Instead of passing an index, pass the actual ScreenPtr. This allows more moving towards not abusing xf86Screens + screenInfo. v2: drop the blockData/wakeupData args as per ajax's suggestion., fix docs. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 790d003de20fb47674420a24dadd92412d78620d Author: Dave Airlie <airlied@gmail.com> Date: Wed Apr 11 09:53:14 2012 +0100 xf86/common: remove some more pScrn->pScreen uses remove some more conversions that appeared after api cleanups. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit aac85e18d1dd093f2cad6bd29375e40bd7af0b8f Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:34:53 2012 +0100 ddc: change API to take ScrnInfoPtr (v2) This removes all xf86Screens usage from ddc code, it modifies the API for some functions to avoid taking indices. v2: address Alan's comments about dropping DDC2Init parameter. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit fe3f57b6eaf6860a33876a54f9439f69578f03a5 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:31:26 2012 +0100 vbe: don't use index for VBEInterpretPanelID (API) Remove use of xf86screens from vbe module. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit abf1965f4ed91529036d3fdb470d6a3ce6f29675 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:25:11 2012 +0100 int10/vbe: don't use xf86Screens. (ABI) (v3) Pass the ScrnInfoPtr instead of the index in the int10 struct. This saves us using it to dereference xf86Screens. v2: address Alan's comment to fix struct alignment. v3: squash in all the int10 fixes, test the vm86 code builds, after comments by Keith. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 23cca612b4fb5efc33683c7624b803b457387e3d Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:30:18 2012 +0100 xserver: drop index argument to ScreenInit (ABI/API) (v2) This drops the index argument, its the same as pScreen->myNum, and its the last major index abuse I can find. v2: address Alan's review - update docs, fix xwin/xnest/darwin Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 40d360e2d7e832407f3ed64e3a02c27ecc89a960 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:23:01 2012 +0100 xf86: migrate PointerMoved from index to ScrnInfoPtr (ABI/API) This migrates PointerMoved from an index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit aa60a2f38679d0eeb979a9c2648c9bc771409bf9 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:20:46 2012 +0100 xf86: migrate PMEvent to a ScrnInfoPtr (ABI/API) This migrates the PMEvent from index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit d3f28ef44371ed4a039ffc5dd7eb6408d1269ba2 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:18:30 2012 +0100 xf86: migrate SetDGAMode from index to ScrnInfoPtr (ABI/API) This migrates the SetDGAMode callback from an index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit baf5e4818a74f2b68c3dfdcc56f54322351039a0 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:14:11 2012 +0100 xf86: migrate ChangeGamma from index to ScrnInfoPtr (ABI/API) (v2) This migrates the ChangeGamma interface to avoid passing a index. v2: fix xf86RandR12.c + xf86cmap.c call Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 51e5f90ada929d6b23176090badbb42fdb3fa550 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:11:09 2012 +0100 xf86/exa: migrate index to screen types for EnableDisableFBAccess (ABI/API) The EXA interface migrates to ScreenPtr, and the xf86 interface migrated to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 94f1f21d17e86f96d4a54292a399160950087675 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:02:11 2012 +0100 xf86: migrate ValidMode callback to ScrnInfoPtr (ABI/API) This migrates the ValidMode to passing a ScrnInfoPtr instead of an index. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3f8f18198fed4f39ec805b508a3482e91eea26b2 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:59:46 2012 +0100 xf86: migrate SwitchMode to taking ScrnInfoPtr (ABI/API) (v2) This migrate the SwitchMode interface to take a ScrnInfoPtr instead of an index. v2: drop flags. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit d06a038a5c49328ab3a8d969d24f9fcd22c63202 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:50:37 2012 +0100 xf86: move AdjustFrame to passing ScrnInfoPtr (ABI/API) (v2) This converts AdjustFrame code paths to passing a ScrnInfoPtr instead of an integer index. v2: drop flags args. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 53d2f8608ffd4090d08e7d5cf2e92fb954959b90 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:41:27 2012 +0100 xf86: modify FreeScreen callback to take pScrn instead of index. (ABI/API) (v2) Another index->pScrn conversion. v2: drop flags arg. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 60db37c0b247052e0f5c54b1921fe58a3609c2e3 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:35:41 2012 +0100 xf86: change EnterVT/LeaveVT to take a ScrnInfoPtr (ABI/API break) (v2) This modifies the EnterVT/LeaveVT interfaces to take a ScrnInfoPtr instead of an index into xf86Screens. This allows dropping more public dereferences of the xf86Screens and screenInfo. v2: drop flags args as suggested by Keith, fix docs. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 06729dbbc804a20242e6499f446acb5d94023c3c Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:04:59 2012 +0100 xserver: remove index from CloseScreen (API/ABI breakage) This drops the index from the CloseScreen callback, its always been useless really, since the pScreen contains it. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-06-05 14:22:18 +02:00
status = (*scrp->ValidMode) (scrp, mode, FALSE,
MODECHECK_INITIAL);
if (status != MODE_OK)
return status;
if (mode->HSync <= 0.0)
mode->HSync = (float) mode->SynthClock / (float) mode->CrtcHTotal;
if (mode->VRefresh <= 0.0)
mode->VRefresh = (mode->SynthClock * 1000.0)
/ (mode->CrtcHTotal * mode->CrtcVTotal);
2003-11-14 17:48:57 +01:00
}
mode->HSync = xf86ModeHSync(mode);
mode->VRefresh = xf86ModeVRefresh(mode);
2003-11-14 17:48:57 +01:00
/* Assume it is OK */
return MODE_OK;
}
/*
* xf86CheckModeForDriver
*
* This function is for checking modes while the server is running (for
* use mainly by the VidMode extension).
*
* This function checks if a mode satisfies a driver's requirements:
* - width lies within the line pitch
* - mode size fits within virtual size
* - horizontal/vertical timings are in range
*
* This function takes the following parameters:
* scrp ScrnInfoPtr
* mode mode to check
* flags not (currently) used
*
* In addition, the following fields from the ScrnInfoRec are used:
* virtualX virtual width
* virtualY virtual height
* clockRanges allowable clock ranges
*/
ModeStatus
2003-11-14 17:48:57 +01:00
xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags)
{
ClockRangePtr cp;
2003-11-14 17:48:57 +01:00
int i, k, gap, minimumGap = CLOCK_TOLERANCE + 1;
int extraFlags = 0;
int clockIndex = -1;
int MulFactor = 1;
int DivFactor = 1;
int ModePrivFlags = 0;
ModeStatus status = MODE_NOMODE;
/* Some sanity checking */
if (scrp == NULL || (!scrp->progClock && scrp->numClocks == 0)) {
ErrorF("xf86CheckModeForDriver: called with invalid scrnInfoRec\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
if (mode == NULL) {
ErrorF("xf86CheckModeForDriver: called with invalid modep\n");
return MODE_ERROR;
2003-11-14 17:48:57 +01:00
}
/* Check the mode size */
if (mode->HDisplay > scrp->virtualX)
return MODE_VIRTUAL_X;
2003-11-14 17:48:57 +01:00
if (mode->VDisplay > scrp->virtualY)
return MODE_VIRTUAL_Y;
2003-11-14 17:48:57 +01:00
for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
/* DivFactor and MulFactor must be > 0 */
cp->ClockDivFactor = max(1, cp->ClockDivFactor);
cp->ClockMulFactor = max(1, cp->ClockMulFactor);
2003-11-14 17:48:57 +01:00
}
if (scrp->progClock) {
/* Check clock is in range */
for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
if (modeInClockRange(cp, mode))
break;
}
if (cp == NULL) {
return MODE_CLOCK_RANGE;
}
/*
* If programmable clock the required mode has been found
*/
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
}
else {
status = MODE_CLOCK_RANGE;
/* Check clock is in range */
for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) {
if (modeInClockRange(cp, mode)) {
/*
* Clock is in range, so if it is not a programmable clock,
* find a matching clock.
*/
i = xf86GetNearestClock(scrp, mode->Clock, 0,
cp->ClockDivFactor, cp->ClockMulFactor,
&k);
/*
* If the clock is too far from the requested clock, this
* mode is no good.
*/
if (k & V_CLKDIV2)
gap = abs((mode->Clock * 2) -
((scrp->clock[i] * cp->ClockDivFactor) /
cp->ClockMulFactor));
else
gap = abs(mode->Clock -
((scrp->clock[i] * cp->ClockDivFactor) /
cp->ClockMulFactor));
if (gap > minimumGap) {
status = MODE_NOCLOCK;
continue;
}
DivFactor = cp->ClockDivFactor;
MulFactor = cp->ClockMulFactor;
ModePrivFlags = cp->PrivFlags;
extraFlags = k;
clockIndex = i;
break;
}
}
if (cp == NULL)
return status;
2003-11-14 17:48:57 +01:00
}
/* Fill in the mode parameters */
if (scrp->progClock) {
mode->ClockIndex = -1;
mode->SynthClock = (mode->Clock * MulFactor) / DivFactor;
2003-11-14 17:48:57 +01:00
}
else {
mode->Clock = (scrp->clock[clockIndex] * DivFactor) / MulFactor;
mode->ClockIndex = clockIndex;
mode->SynthClock = scrp->clock[clockIndex];
if (extraFlags & V_CLKDIV2) {
mode->Clock /= 2;
mode->SynthClock /= 2;
}
}
mode->PrivFlags = ModePrivFlags;
2003-11-14 17:48:57 +01:00
return MODE_OK;
}
static int
inferVirtualSize(ScrnInfoPtr scrp, DisplayModePtr modes, int *vx, int *vy)
{
float aspect = 0.0;
MonPtr mon = scrp->monitor;
xf86MonPtr DDC;
int x = 0, y = 0;
DisplayModePtr mode;
if (!mon)
return 0;
DDC = mon->DDC;
if (DDC && DDC->ver.revision >= 4) {
/* For 1.4, we might actually get native pixel format. How novel. */
if (PREFERRED_TIMING_MODE(DDC->features.msc)) {
for (mode = modes; mode; mode = mode->next) {
if (mode->type & (M_T_DRIVER | M_T_PREFERRED)) {
x = mode->HDisplay;
y = mode->VDisplay;
goto found;
}
}
}
/*
* Even if we don't, we might get aspect ratio from extra CVT info
* or from the monitor size fields. TODO.
*/
}
/*
* Technically this triggers if either is zero. That wasn't legal
* before EDID 1.4, but right now we'll get that wrong. TODO.
*/
if (!aspect) {
if (!mon->widthmm || !mon->heightmm)
aspect = 4.0 / 3.0;
else
aspect = (float) mon->widthmm / (float) mon->heightmm;
}
/* find the largest M_T_DRIVER mode with that aspect ratio */
for (mode = modes; mode; mode = mode->next) {
float mode_aspect, metaspect;
if (!(mode->type & (M_T_DRIVER | M_T_USERDEF)))
continue;
mode_aspect = (float) mode->HDisplay / (float) mode->VDisplay;
metaspect = aspect / mode_aspect;
/* 5% slop or so, since we only get size in centimeters */
if (fabs(1.0 - metaspect) < 0.05) {
if ((mode->HDisplay > x) && (mode->VDisplay > y)) {
x = mode->HDisplay;
y = mode->VDisplay;
}
}
}
if (!x || !y) {
xf86DrvMsg(scrp->scrnIndex, X_WARNING,
"Unable to estimate virtual size\n");
return 0;
}
found:
*vx = x;
*vy = y;
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"Estimated virtual size for aspect ratio %.4f is %dx%d\n",
aspect, *vx, *vy);
return 1;
}
/* Least common multiple */
static unsigned int
LCM(unsigned int x, unsigned int y)
{
unsigned int m = x, n = y, o;
while ((o = m % n)) {
m = n;
n = o;
}
return (x / n) * y;
}
/*
* Given various screen attributes, determine the minimum scanline width such
* that each scanline is server and DDX padded and any pixels with embedded
* bank boundaries are off-screen. This function returns -1 if such a width
* cannot exist.
*/
static int
scanLineWidth(unsigned int xsize, /* pixels */
unsigned int ysize, /* pixels */
unsigned int width, /* pixels */
unsigned long BankSize, /* char's */
PixmapFormatRec * pBankFormat, unsigned int nWidthUnit /* bits */
)
{
unsigned long nBitsPerBank, nBitsPerScanline, nBitsPerScanlinePadUnit;
unsigned long minBitsPerScanline, maxBitsPerScanline;
/* Sanity checks */
if (!nWidthUnit || !pBankFormat)
return -1;
nBitsPerBank = BankSize * 8;
if (nBitsPerBank % pBankFormat->scanlinePad)
return -1;
if (xsize > width)
width = xsize;
nBitsPerScanlinePadUnit = LCM(pBankFormat->scanlinePad, nWidthUnit);
nBitsPerScanline =
(((width * pBankFormat->bitsPerPixel) + nBitsPerScanlinePadUnit - 1) /
nBitsPerScanlinePadUnit) * nBitsPerScanlinePadUnit;
width = nBitsPerScanline / pBankFormat->bitsPerPixel;
if (!xsize || !(nBitsPerBank % pBankFormat->bitsPerPixel))
return (int) width;
/*
* Scanlines will be server-pad aligned at this point. They will also be
* a multiple of nWidthUnit bits long. Ensure that pixels with embedded
* bank boundaries are off-screen.
*
* It seems reasonable to limit total frame buffer size to 1/16 of the
* theoretical maximum address space size. On a machine with 32-bit
* addresses (to 8-bit quantities) this turns out to be 256MB. Not only
* does this provide a simple limiting condition for the loops below, but
* it also prevents unsigned long wraparounds.
*/
if (!ysize)
return -1;
minBitsPerScanline = xsize * pBankFormat->bitsPerPixel;
if (minBitsPerScanline > nBitsPerBank)
return -1;
if (ysize == 1)
return (int) width;
maxBitsPerScanline =
(((unsigned long) (-1) >> 1) - minBitsPerScanline) / (ysize - 1);
while (nBitsPerScanline <= maxBitsPerScanline) {
unsigned long BankBase, BankUnit;
BankUnit = ((nBitsPerBank + nBitsPerScanline - 1) / nBitsPerBank) *
nBitsPerBank;
if (!(BankUnit % nBitsPerScanline))
return (int) width;
for (BankBase = BankUnit;; BankBase += nBitsPerBank) {
unsigned long x, y;
y = BankBase / nBitsPerScanline;
if (y >= ysize)
return (int) width;
x = BankBase % nBitsPerScanline;
if (!(x % pBankFormat->bitsPerPixel))
continue;
if (x < minBitsPerScanline) {
/*
* Skip ahead certain widths by dividing the excess scanline
* amongst the y's.
*/
y *= nBitsPerScanlinePadUnit;
nBitsPerScanline += ((x + y - 1) / y) * nBitsPerScanlinePadUnit;
width = nBitsPerScanline / pBankFormat->bitsPerPixel;
break;
}
if (BankBase != BankUnit)
continue;
if (!(nBitsPerScanline % x))
return (int) width;
BankBase = ((nBitsPerScanline - minBitsPerScanline) /
(nBitsPerScanline - x)) * BankUnit;
}
}
return -1;
}
2003-11-14 17:48:57 +01:00
/*
* xf86ValidateModes
*
* This function takes a set of mode names, modes and limiting conditions,
* and selects a set of modes and parameters based on those conditions.
*
* This function takes the following parameters:
* scrp ScrnInfoPtr
* availModes the list of modes available for the monitor
* modeNames (optional) list of mode names that the screen is requesting
* clockRanges a list of clock ranges
* linePitches (optional) a list of line pitches
* minPitch (optional) minimum line pitch (in pixels)
* maxPitch (optional) maximum line pitch (in pixels)
* pitchInc (mandatory) pitch increment (in bits)
* minHeight (optional) minimum virtual height (in pixels)
* maxHeight (optional) maximum virtual height (in pixels)
* virtualX (optional) virtual width requested (in pixels)
* virtualY (optional) virtual height requested (in pixels)
* apertureSize size of video aperture (in bytes)
* strategy how to decide which mode to use from multiple modes with
* the same name
*
* In addition, the following fields from the ScrnInfoRec are used:
* clocks a list of discrete clocks
* numClocks number of discrete clocks
* progClock clock is programmable
* monitor pointer to structure for monitor section
* fbFormat format of the framebuffer
* videoRam video memory size
* xInc horizontal timing increment (defaults to 8 pixels)
*
* The function fills in the following ScrnInfoRec fields:
* modePool A subset of the modes available to the monitor which
* are compatible with the driver.
* modes one mode entry for each of the requested modes, with the
* status field filled in to indicate if the mode has been
* accepted or not.
* virtualX the resulting virtual width
* virtualY the resulting virtual height
* displayWidth the resulting line pitch
*
* The function's return value is the number of matching modes found, or -1
* if an unrecoverable error was encountered.
*/
int
2003-11-14 17:48:57 +01:00
xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes,
const char **modeNames, ClockRangePtr clockRanges,
int *linePitches, int minPitch, int maxPitch, int pitchInc,
int minHeight, int maxHeight, int virtualX, int virtualY,
int apertureSize, LookupModeFlags strategy)
2003-11-14 17:48:57 +01:00
{
DisplayModePtr p, q, r, new, last, *endp;
int i, numModes = 0;
ModeStatus status;
int linePitch = -1, virtX = 0, virtY = 0;
int newLinePitch, newVirtX, newVirtY;
int modeSize; /* in pixels */
Bool validateAllDefaultModes = FALSE;
2003-11-14 17:48:57 +01:00
Bool userModes = FALSE;
int saveType;
PixmapFormatRec *BankFormat;
ClockRangePtr cp;
int numTimings = 0;
range hsync[MAX_HSYNC];
range vrefresh[MAX_VREFRESH];
Bool inferred_virtual = FALSE;
2003-11-14 17:48:57 +01:00
DebugF
("xf86ValidateModes(%p, %p, %p, %p,\n\t\t %p, %d, %d, %d, %d, %d, %d, %d, %d, 0x%x)\n",
scrp, availModes, modeNames, clockRanges, linePitches, minPitch,
maxPitch, pitchInc, minHeight, maxHeight, virtualX, virtualY,
apertureSize, strategy);
2003-11-14 17:48:57 +01:00
/* Some sanity checking */
if (scrp == NULL || scrp->name == NULL || !scrp->monitor ||
(!scrp->progClock && scrp->numClocks == 0)) {
ErrorF("xf86ValidateModes: called with invalid scrnInfoRec\n");
return -1;
2003-11-14 17:48:57 +01:00
}
if (linePitches != NULL && linePitches[0] <= 0) {
ErrorF("xf86ValidateModes: called with invalid linePitches\n");
return -1;
2003-11-14 17:48:57 +01:00
}
if (pitchInc <= 0) {
ErrorF("xf86ValidateModes: called with invalid pitchInc\n");
return -1;
2003-11-14 17:48:57 +01:00
}
if ((virtualX > 0) != (virtualY > 0)) {
ErrorF("xf86ValidateModes: called with invalid virtual resolution\n");
return -1;
2003-11-14 17:48:57 +01:00
}
/*
* If requested by the driver, allow missing hsync and/or vrefresh ranges
* in the monitor section.
*/
if (strategy & LOOKUP_OPTIONAL_TOLERANCES) {
strategy &= ~LOOKUP_OPTIONAL_TOLERANCES;
}
else {
const char *type = "";
Bool specified = FALSE;
if (scrp->monitor->nHsync <= 0) {
if (numTimings > 0) {
scrp->monitor->nHsync = numTimings;
for (i = 0; i < numTimings; i++) {
scrp->monitor->hsync[i].lo = hsync[i].lo;
scrp->monitor->hsync[i].hi = hsync[i].hi;
}
}
else {
scrp->monitor->hsync[0].lo = 31.5;
scrp->monitor->hsync[0].hi = 48.0;
scrp->monitor->nHsync = 1;
}
type = "default ";
}
else {
specified = TRUE;
}
for (i = 0; i < scrp->monitor->nHsync; i++) {
if (scrp->monitor->hsync[i].lo == scrp->monitor->hsync[i].hi)
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"%s: Using %shsync value of %.2f kHz\n",
scrp->monitor->id, type, scrp->monitor->hsync[i].lo);
else
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"%s: Using %shsync range of %.2f-%.2f kHz\n",
scrp->monitor->id, type,
scrp->monitor->hsync[i].lo,
scrp->monitor->hsync[i].hi);
}
type = "";
if (scrp->monitor->nVrefresh <= 0) {
if (numTimings > 0) {
scrp->monitor->nVrefresh = numTimings;
for (i = 0; i < numTimings; i++) {
scrp->monitor->vrefresh[i].lo = vrefresh[i].lo;
scrp->monitor->vrefresh[i].hi = vrefresh[i].hi;
}
}
else {
scrp->monitor->vrefresh[0].lo = 50;
scrp->monitor->vrefresh[0].hi = 70;
scrp->monitor->nVrefresh = 1;
}
type = "default ";
}
else {
specified = TRUE;
}
for (i = 0; i < scrp->monitor->nVrefresh; i++) {
if (scrp->monitor->vrefresh[i].lo == scrp->monitor->vrefresh[i].hi)
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"%s: Using %svrefresh value of %.2f Hz\n",
scrp->monitor->id, type,
scrp->monitor->vrefresh[i].lo);
else
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"%s: Using %svrefresh range of %.2f-%.2f Hz\n",
scrp->monitor->id, type,
scrp->monitor->vrefresh[i].lo,
scrp->monitor->vrefresh[i].hi);
}
type = "";
if (!scrp->monitor->maxPixClock && !specified) {
type = "default ";
scrp->monitor->maxPixClock = 65000.0;
}
if (scrp->monitor->maxPixClock) {
xf86DrvMsg(scrp->scrnIndex, X_INFO,
"%s: Using %smaximum pixel clock of %.2f MHz\n",
scrp->monitor->id, type,
(float) scrp->monitor->maxPixClock / 1000.0);
}
2003-11-14 17:48:57 +01:00
}
/*
* Store the clockRanges for later use by the VidMode extension.
2003-11-14 17:48:57 +01:00
*/
Make xf86ValidateModes actually copy clock range list to screen pointer Our in-house parfait 1.1 code analysis tool complained that every exit path from xf86ValidateModes() in hw/xfree86/common/xf86Mode.c leaks the storeClockRanges allocation made at line 1501 with XNFalloc. Investigating, it seems that this code to copy the clock range list to the clockRanges list in the screen pointer is just plain insane, and according to git, has been since we first imported it from XFree86. We start at line 1495 by walking the linked list from scrp->clockRanges until we find the end. But that was just a diversion, since we've found the end and immediately forgotten it, and thus at 1499 we know that storeClockRanges is NULL, but that's not a problem since we're going to immediately overwrite that value as the first thing in the loop. So we move on through this loop at 1499, which takes us through the linked list from the clockRanges variable, and for every entry in that list allocates a new structure and copies cp to it. If we've not filled in the screen's clockRanges pointer yet, we set it to the first storeClockRanges we copied from cp. Otherwise, as best I can tell, we just drop it into memory and let it leak away, as parfait warned. And then we hit the loop action, which if we haven't hit the end of the cp list, advances cp to the next item in the list, and then just for the fun of it, also sets storeClockRanges to the ->next pointer it has just copied from cp as well, even though it's going to overwrite it as the very first instruction in the loop body. v2: rewritten using nt_list_* macros from Xorg's list.h header Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-01-27 22:10:08 +01:00
nt_list_for_each_entry(cp, clockRanges, next) {
ClockRangePtr newCR = xnfalloc(sizeof(ClockRange));
memcpy(newCR, cp, sizeof(ClockRange));
newCR->next = NULL;
if (scrp->clockRanges == NULL)
Make xf86ValidateModes actually copy clock range list to screen pointer Our in-house parfait 1.1 code analysis tool complained that every exit path from xf86ValidateModes() in hw/xfree86/common/xf86Mode.c leaks the storeClockRanges allocation made at line 1501 with XNFalloc. Investigating, it seems that this code to copy the clock range list to the clockRanges list in the screen pointer is just plain insane, and according to git, has been since we first imported it from XFree86. We start at line 1495 by walking the linked list from scrp->clockRanges until we find the end. But that was just a diversion, since we've found the end and immediately forgotten it, and thus at 1499 we know that storeClockRanges is NULL, but that's not a problem since we're going to immediately overwrite that value as the first thing in the loop. So we move on through this loop at 1499, which takes us through the linked list from the clockRanges variable, and for every entry in that list allocates a new structure and copies cp to it. If we've not filled in the screen's clockRanges pointer yet, we set it to the first storeClockRanges we copied from cp. Otherwise, as best I can tell, we just drop it into memory and let it leak away, as parfait warned. And then we hit the loop action, which if we haven't hit the end of the cp list, advances cp to the next item in the list, and then just for the fun of it, also sets storeClockRanges to the ->next pointer it has just copied from cp as well, even though it's going to overwrite it as the very first instruction in the loop body. v2: rewritten using nt_list_* macros from Xorg's list.h header Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
2013-01-27 22:10:08 +01:00
scrp->clockRanges = newCR;
else
nt_list_append(newCR, scrp->clockRanges, ClockRange, next);
2003-11-14 17:48:57 +01:00
}
/* Determine which pixmap format to pass to scanLineWidth() */
2003-11-14 17:48:57 +01:00
if (scrp->depth > 4)
BankFormat = &scrp->fbFormat;
2003-11-14 17:48:57 +01:00
else
BankFormat = xf86GetPixFormat(scrp, 1); /* >not< scrp->depth! */
2003-11-14 17:48:57 +01:00
if (scrp->xInc <= 0)
scrp->xInc = 8; /* Suitable for VGA and others */
2003-11-14 17:48:57 +01:00
#define _VIRTUALX(x) ((((x) + scrp->xInc - 1) / scrp->xInc) * scrp->xInc)
/*
* Determine maxPitch if it wasn't given explicitly. Note linePitches
* always takes precedence if is non-NULL. In that case the minPitch and
* maxPitch values passed are ignored.
*/
if (linePitches) {
minPitch = maxPitch = linePitches[0];
for (i = 1; linePitches[i] > 0; i++) {
if (linePitches[i] > maxPitch)
maxPitch = linePitches[i];
if (linePitches[i] < minPitch)
minPitch = linePitches[i];
}
2003-11-14 17:48:57 +01:00
}
/*
* Initialise virtX and virtY if the values are fixed.
*/
if (virtualY > 0) {
if (maxHeight > 0 && virtualY > maxHeight) {
xf86DrvMsg(scrp->scrnIndex, X_ERROR,
"Virtual height (%d) is too large for the hardware "
"(max %d)\n", virtualY, maxHeight);
return -1;
}
if (minHeight > 0 && virtualY < minHeight) {
xf86DrvMsg(scrp->scrnIndex, X_ERROR,
"Virtual height (%d) is too small for the hardware "
"(min %d)\n", virtualY, minHeight);
return -1;
}
virtualX = _VIRTUALX(virtualX);
if (linePitches != NULL) {
for (i = 0; linePitches[i] != 0; i++) {
if ((linePitches[i] >= virtualX) &&
(linePitches[i] ==
scanLineWidth(virtualX, virtualY, linePitches[i],
apertureSize, BankFormat, pitchInc))) {
linePitch = linePitches[i];
break;
}
}
}
else {
linePitch = scanLineWidth(virtualX, virtualY, minPitch,
apertureSize, BankFormat, pitchInc);
}
if ((linePitch < minPitch) || (linePitch > maxPitch)) {
xf86DrvMsg(scrp->scrnIndex, X_ERROR,
"Virtual width (%d) is too large for the hardware "
"(max %d)\n", virtualX, maxPitch);
return -1;
}
if (!xf86CheckModeSize(scrp, linePitch, virtualX, virtualY)) {
xf86DrvMsg(scrp->scrnIndex, X_ERROR,
"Virtual size (%dx%d) (pitch %d) exceeds video memory\n",
virtualX, virtualY, linePitch);
return -1;
}
virtX = virtualX;
virtY = virtualY;
}
else if (!modeNames || !*modeNames) {
/* No virtual size given in the config, try to infer */
/* XXX this doesn't take m{in,ax}Pitch into account; oh well */
inferred_virtual = inferVirtualSize(scrp, availModes, &virtX, &virtY);
if (inferred_virtual)
linePitch = scanLineWidth(virtX, virtY, minPitch, apertureSize,
BankFormat, pitchInc);
2003-11-14 17:48:57 +01:00
}
/* Print clock ranges and scaled clocks */
xf86ShowClockRanges(scrp, clockRanges);
/*
* If scrp->modePool hasn't been setup yet, set it up now. This allows the
* modes that the driver definitely can't use to be weeded out early. Note
* that a modePool mode's prev field is used to hold a pointer to the
* member of the scrp->modes list for which a match was considered.
*/
if (scrp->modePool == NULL) {
q = NULL;
for (p = availModes; p != NULL; p = p->next) {
status = xf86InitialCheckModeForDriver(scrp, p, clockRanges,
strategy, maxPitch,
virtX, virtY);
if (status == MODE_OK) {
status = xf86CheckModeForMonitor(p, scrp->monitor);
}
if (status == MODE_OK) {
new = xnfalloc(sizeof(DisplayModeRec));
*new = *p;
new->next = NULL;
if (!q) {
scrp->modePool = new;
}
else {
q->next = new;
}
new->prev = NULL;
q = new;
q->name = xnfstrdup(p->name);
q->status = MODE_OK;
}
else {
printModeRejectMessage(scrp->scrnIndex, p, status);
}
}
if (scrp->modePool == NULL) {
xf86DrvMsg(scrp->scrnIndex, X_WARNING, "Mode pool is empty\n");
return 0;
}
}
else {
for (p = scrp->modePool; p != NULL; p = p->next) {
p->prev = NULL;
p->status = MODE_OK;
}
2003-11-14 17:48:57 +01:00
}
/*
* Allocate one entry in scrp->modes for each named mode.
*/
while (scrp->modes)
xf86DeleteMode(&scrp->modes, scrp->modes);
2003-11-14 17:48:57 +01:00
endp = &scrp->modes;
last = NULL;
if (modeNames != NULL) {
for (i = 0; modeNames[i] != NULL; i++) {
userModes = TRUE;
new = xnfcalloc(1, sizeof(DisplayModeRec));
new->prev = last;
new->type = M_T_USERDEF;
new->name = xnfstrdup(modeNames[i]);
if (new->prev)
new->prev->next = new;
*endp = last = new;
endp = &new->next;
}
2003-11-14 17:48:57 +01:00
}
/* Lookup each mode */
#ifdef PANORAMIX
if (noPanoramiXExtension)
validateAllDefaultModes = TRUE;
#endif
for (p = scrp->modes;; p = p->next) {
Bool repeat;
/*
* If the supplied mode names don't produce a valid mode, scan through
* unconsidered modePool members until one survives validation. This
* is done in decreasing order by mode pixel area.
*/
if (p == NULL) {
if ((numModes > 0) && !validateAllDefaultModes)
break;
validateAllDefaultModes = TRUE;
r = NULL;
modeSize = 0;
for (q = scrp->modePool; q != NULL; q = q->next) {
if ((q->prev == NULL) && (q->status == MODE_OK)) {
/*
* Deal with the case where this mode wasn't considered
* because of a builtin mode of the same name.
*/
for (p = scrp->modes; p != NULL; p = p->next) {
if ((p->status != MODE_OK) && !strcmp(p->name, q->name))
break;
}
if (p != NULL)
q->prev = p;
else {
/*
* A quick check to not allow default modes with
* horizontal timing parameters that CRTs may have
* problems with.
*/
if (!scrp->monitor->reducedblanking &&
(q->type & M_T_DEFAULT) &&
((double) q->HTotal / (double) q->HDisplay) < 1.15)
continue;
if (modeSize < (q->HDisplay * q->VDisplay)) {
r = q;
modeSize = q->HDisplay * q->VDisplay;
}
}
}
}
if (r == NULL)
break;
p = xnfcalloc(1, sizeof(DisplayModeRec));
p->prev = last;
p->name = xnfstrdup(r->name);
if (!userModes)
p->type = M_T_USERDEF;
if (p->prev)
p->prev->next = p;
*endp = last = p;
endp = &p->next;
}
repeat = FALSE;
lookupNext:
if (repeat && ((status = p->status) != MODE_OK))
printModeRejectMessage(scrp->scrnIndex, p, status);
saveType = p->type;
status = xf86LookupMode(scrp, p, clockRanges, strategy);
if (repeat && status == MODE_NOMODE)
continue;
if (status != MODE_OK)
printModeRejectMessage(scrp->scrnIndex, p, status);
if (status == MODE_ERROR) {
ErrorF("xf86ValidateModes: "
"unexpected result from xf86LookupMode()\n");
return -1;
}
if (status != MODE_OK) {
if (p->status == MODE_OK)
p->status = status;
continue;
}
p->type |= saveType;
repeat = TRUE;
newLinePitch = linePitch;
newVirtX = virtX;
newVirtY = virtY;
/*
* Don't let non-user defined modes increase the virtual size
*/
if (!(p->type & M_T_USERDEF) && (numModes > 0)) {
if (p->HDisplay > virtX) {
p->status = MODE_VIRTUAL_X;
goto lookupNext;
}
if (p->VDisplay > virtY) {
p->status = MODE_VIRTUAL_Y;
goto lookupNext;
}
}
/*
* Adjust virtual width and height if the mode is too large for the
* current values and if they are not fixed.
*/
if (virtualX <= 0 && p->HDisplay > newVirtX)
newVirtX = _VIRTUALX(p->HDisplay);
if (virtualY <= 0 && p->VDisplay > newVirtY) {
if (maxHeight > 0 && p->VDisplay > maxHeight) {
p->status = MODE_VIRTUAL_Y; /* ? */
goto lookupNext;
}
newVirtY = p->VDisplay;
}
/*
* If virtual resolution is to be increased, revalidate it.
*/
if ((virtX != newVirtX) || (virtY != newVirtY)) {
if (linePitches != NULL) {
newLinePitch = -1;
for (i = 0; linePitches[i] != 0; i++) {
if ((linePitches[i] >= newVirtX) &&
(linePitches[i] >= linePitch) &&
(linePitches[i] ==
scanLineWidth(newVirtX, newVirtY, linePitches[i],
apertureSize, BankFormat, pitchInc))) {
newLinePitch = linePitches[i];
break;
}
}
}
else {
if (linePitch < minPitch)
linePitch = minPitch;
newLinePitch = scanLineWidth(newVirtX, newVirtY, linePitch,
apertureSize, BankFormat,
pitchInc);
}
if ((newLinePitch < minPitch) || (newLinePitch > maxPitch)) {
p->status = MODE_BAD_WIDTH;
goto lookupNext;
}
/*
* Check that the pixel area required by the new virtual height
* and line pitch isn't too large.
*/
if (!xf86CheckModeSize(scrp, newLinePitch, newVirtX, newVirtY)) {
p->status = MODE_MEM_VIRT;
goto lookupNext;
}
}
if (scrp->ValidMode) {
/*
* Give the driver a final say, passing it the proposed virtual
* geometry.
*/
scrp->virtualX = newVirtX;
scrp->virtualY = newVirtY;
scrp->displayWidth = newLinePitch;
api: rework the X server driver API to avoid global arrays. This is a squash merge containing all the API changes, as well as the video ABI bump. Its been squashed to make bisection easier. Full patch log below: commit b202738bbf0c5a1c1172767119c2c71f1e7f8070 Author: Aaron Plattner <aplattner@nvidia.com> Date: Mon May 14 15:16:11 2012 -0700 xfree86: Bump video ABI to 13.0 The ABI was broken by changes to convert from screen index numbers to ScreenPtr / ScrnInfoPtr in various structures and function signatures. Signed-off-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3d5f7d9f8d408bcad3f83277d255f25d3b0edbf3 Author: Dave Airlie <airlied@redhat.com> Date: Thu May 24 10:56:57 2012 +0100 xf86: xf86ClearEntityListForScreen should take a pScrn When adding GPU screens this make life easier. (also fix comment, as pointed out by Alan) Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Dave Airlie <airlied@redhat.com> commit afee8b5ab4501597ecc1ade34124d7ca227ab055 Author: Dave Airlie <airlied@redhat.com> Date: Thu May 24 07:07:32 2012 +0100 xf86i2c: add pscrn for drivers to use This just adds a pScrn pointer into the struct for the drivers to use instead of scrnIndex. Mostly scrnIndex is used for logging, but some drivers use it to lookup xf86Screens, so let them stash a pScrn instead. Removing the scrnIndex is a bit more involved and I'm not sure its worth the effort. Doing i2c in the X server is legacy code as far as I'm concerned. Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit ea5092f1f679691d187f1eee9427e6057beec56e Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 19:25:20 2012 +0100 dix/gc: consolidate GC object creation in one place The standard GC create and scratch GC create were 90% the same really, and I have a need in the future for creating GC objects without the other bits, so wanted to avoid a third copy. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3d91482ea9b4883e64e496f2768168e0ffa21ba1 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 10:24:06 2012 +0100 xf86: add a define to denote the new non-index interfaces are being used This can be used by drivers to provide compatible APIs. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 37c3ae3e6cd4f3dedc72f371096d6743f8f99df3 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 15:09:12 2012 +0100 dix: make Create/Free scratch pixmaps take a ScreenPtr While technically an API/ABI change I doubt anyone uses it, but it helps in splitting screens up. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 75f2062a3fe94f04764ecc7d2ff2fbbeccb9da60 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:57:55 2012 +0100 xf86/xv: remove scrnIndexfrom xf86FindXvOptions. Move this interface to taking an ScrnInfoPtr. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit f80c2374f40ea7b2ee0556e2e76cc07406f3d843 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:53:59 2012 +0100 xf86: make xf86DeleteScreen take a ScrnInfoPtr (v2) stop passing indices into this function. v2: drop flags argument. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 58824e414f35682435f15bfe6c4b656bd90b9235 Author: Dave Airlie <airlied@redhat.com> Date: Wed May 23 14:48:09 2012 +0100 xf86: fix xf86IsScreenPrimary interface to take a pScrn (API/ABI) Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 6b4fc1f9d391bcdf7ca288766e49bce60f4635cd Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:18:59 2012 +0100 xserver: convert block/wakeup handlers to passing ScreenPtr (ABI/API) (v2) Instead of passing an index, pass the actual ScreenPtr. This allows more moving towards not abusing xf86Screens + screenInfo. v2: drop the blockData/wakeupData args as per ajax's suggestion., fix docs. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 790d003de20fb47674420a24dadd92412d78620d Author: Dave Airlie <airlied@gmail.com> Date: Wed Apr 11 09:53:14 2012 +0100 xf86/common: remove some more pScrn->pScreen uses remove some more conversions that appeared after api cleanups. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit aac85e18d1dd093f2cad6bd29375e40bd7af0b8f Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:34:53 2012 +0100 ddc: change API to take ScrnInfoPtr (v2) This removes all xf86Screens usage from ddc code, it modifies the API for some functions to avoid taking indices. v2: address Alan's comments about dropping DDC2Init parameter. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit fe3f57b6eaf6860a33876a54f9439f69578f03a5 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:31:26 2012 +0100 vbe: don't use index for VBEInterpretPanelID (API) Remove use of xf86screens from vbe module. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit abf1965f4ed91529036d3fdb470d6a3ce6f29675 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 16:25:11 2012 +0100 int10/vbe: don't use xf86Screens. (ABI) (v3) Pass the ScrnInfoPtr instead of the index in the int10 struct. This saves us using it to dereference xf86Screens. v2: address Alan's comment to fix struct alignment. v3: squash in all the int10 fixes, test the vm86 code builds, after comments by Keith. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 23cca612b4fb5efc33683c7624b803b457387e3d Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:30:18 2012 +0100 xserver: drop index argument to ScreenInit (ABI/API) (v2) This drops the index argument, its the same as pScreen->myNum, and its the last major index abuse I can find. v2: address Alan's review - update docs, fix xwin/xnest/darwin Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 40d360e2d7e832407f3ed64e3a02c27ecc89a960 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:23:01 2012 +0100 xf86: migrate PointerMoved from index to ScrnInfoPtr (ABI/API) This migrates PointerMoved from an index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit aa60a2f38679d0eeb979a9c2648c9bc771409bf9 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:20:46 2012 +0100 xf86: migrate PMEvent to a ScrnInfoPtr (ABI/API) This migrates the PMEvent from index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit d3f28ef44371ed4a039ffc5dd7eb6408d1269ba2 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:18:30 2012 +0100 xf86: migrate SetDGAMode from index to ScrnInfoPtr (ABI/API) This migrates the SetDGAMode callback from an index to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit baf5e4818a74f2b68c3dfdcc56f54322351039a0 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:14:11 2012 +0100 xf86: migrate ChangeGamma from index to ScrnInfoPtr (ABI/API) (v2) This migrates the ChangeGamma interface to avoid passing a index. v2: fix xf86RandR12.c + xf86cmap.c call Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 51e5f90ada929d6b23176090badbb42fdb3fa550 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:11:09 2012 +0100 xf86/exa: migrate index to screen types for EnableDisableFBAccess (ABI/API) The EXA interface migrates to ScreenPtr, and the xf86 interface migrated to ScrnInfoPtr. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 94f1f21d17e86f96d4a54292a399160950087675 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 15:02:11 2012 +0100 xf86: migrate ValidMode callback to ScrnInfoPtr (ABI/API) This migrates the ValidMode to passing a ScrnInfoPtr instead of an index. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 3f8f18198fed4f39ec805b508a3482e91eea26b2 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:59:46 2012 +0100 xf86: migrate SwitchMode to taking ScrnInfoPtr (ABI/API) (v2) This migrate the SwitchMode interface to take a ScrnInfoPtr instead of an index. v2: drop flags. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit d06a038a5c49328ab3a8d969d24f9fcd22c63202 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:50:37 2012 +0100 xf86: move AdjustFrame to passing ScrnInfoPtr (ABI/API) (v2) This converts AdjustFrame code paths to passing a ScrnInfoPtr instead of an integer index. v2: drop flags args. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 53d2f8608ffd4090d08e7d5cf2e92fb954959b90 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:41:27 2012 +0100 xf86: modify FreeScreen callback to take pScrn instead of index. (ABI/API) (v2) Another index->pScrn conversion. v2: drop flags arg. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 60db37c0b247052e0f5c54b1921fe58a3609c2e3 Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:35:41 2012 +0100 xf86: change EnterVT/LeaveVT to take a ScrnInfoPtr (ABI/API break) (v2) This modifies the EnterVT/LeaveVT interfaces to take a ScrnInfoPtr instead of an index into xf86Screens. This allows dropping more public dereferences of the xf86Screens and screenInfo. v2: drop flags args as suggested by Keith, fix docs. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com> commit 06729dbbc804a20242e6499f446acb5d94023c3c Author: Dave Airlie <airlied@gmail.com> Date: Tue Apr 10 14:04:59 2012 +0100 xserver: remove index from CloseScreen (API/ABI breakage) This drops the index from the CloseScreen callback, its always been useless really, since the pScreen contains it. Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> Acked-by: Aaron Plattner <aplattner@nvidia.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
2012-06-05 14:22:18 +02:00
p->status = (scrp->ValidMode) (scrp, p, FALSE,
MODECHECK_FINAL);
if (p->status != MODE_OK) {
goto lookupNext;
}
}
/* Mode has passed all the tests */
virtX = newVirtX;
virtY = newVirtY;
linePitch = newLinePitch;
p->status = MODE_OK;
numModes++;
2003-11-14 17:48:57 +01:00
}
/*
* If we estimated the virtual size above, we may have filtered away all
* the modes that maximally match that size; scan again to find out and
* fix up if so.
*/
if (inferred_virtual) {
int vx = 0, vy = 0;
for (p = scrp->modes; p; p = p->next) {
if (p->HDisplay > vx && p->VDisplay > vy) {
vx = p->HDisplay;
vy = p->VDisplay;
}
}
if (vx < virtX || vy < virtY) {
const int types[] = {
M_T_BUILTIN | M_T_PREFERRED,
M_T_BUILTIN,
M_T_DRIVER | M_T_PREFERRED,
M_T_DRIVER,
0
};
const int ntypes = ARRAY_SIZE(types);
int n;
/*
* We did not find the estimated virtual size. So now we want to
* find the largest mode available, but we want to search in the
* modes in the order of "types" listed above.
*/
for (n = 0; n < ntypes; n++) {
int type = types[n];
vx = 0;
vy = 0;
for (p = scrp->modes; p; p = p->next) {
/* scan through the modes in the sort order above */
if ((p->type & type) != type)
continue;
if (p->HDisplay > vx && p->VDisplay > vy) {
vx = p->HDisplay;
vy = p->VDisplay;
}
}
if (vx && vy)
/* Found one */
break;
}
xf86DrvMsg(scrp->scrnIndex, X_WARNING,
"Shrinking virtual size estimate from %dx%d to %dx%d\n",
virtX, virtY, vx, vy);
virtX = _VIRTUALX(vx);
virtY = vy;
for (p = scrp->modes; p; p = p->next) {
if (numModes > 0) {
if (p->HDisplay > virtX)
p->status = MODE_VIRTUAL_X;
if (p->VDisplay > virtY)
p->status = MODE_VIRTUAL_Y;
if (p->status != MODE_OK) {
numModes--;
printModeRejectMessage(scrp->scrnIndex, p, p->status);
}
}
}
if (linePitches != NULL) {
for (i = 0; linePitches[i] != 0; i++) {
if ((linePitches[i] >= virtX) &&
(linePitches[i] ==
scanLineWidth(virtX, virtY, linePitches[i],
apertureSize, BankFormat, pitchInc))) {
linePitch = linePitches[i];
break;
}
}
}
else {
linePitch = scanLineWidth(virtX, virtY, minPitch,
apertureSize, BankFormat, pitchInc);
}
}
}
2003-11-14 17:48:57 +01:00
/* Update the ScrnInfoRec parameters */
2003-11-14 17:48:57 +01:00
scrp->virtualX = virtX;
scrp->virtualY = virtY;
scrp->displayWidth = linePitch;
if (numModes <= 0)
return 0;
2003-11-14 17:48:57 +01:00
/* Make the mode list into a circular list by joining up the ends */
p = scrp->modes;
while (p->next != NULL)
p = p->next;
2003-11-14 17:48:57 +01:00
/* p is now the last mode on the list */
p->next = scrp->modes;
scrp->modes->prev = p;
if (minHeight > 0 && virtY < minHeight) {
xf86DrvMsg(scrp->scrnIndex, X_ERROR,
"Virtual height (%d) is too small for the hardware "
"(min %d)\n", virtY, minHeight);
return -1;
2003-11-14 17:48:57 +01:00
}
return numModes;
}
/*
* xf86DeleteMode
*
* This function removes a mode from a list of modes.
*
* There are different types of mode lists:
*
* - singly linked linear lists, ending in NULL
* - doubly linked linear lists, starting and ending in NULL
* - doubly linked circular lists
*
*/
void
xf86DeleteMode(DisplayModePtr * modeList, DisplayModePtr mode)
2003-11-14 17:48:57 +01:00
{
/* Catch the easy/insane cases */
if (modeList == NULL || *modeList == NULL || mode == NULL)
return;
2003-11-14 17:48:57 +01:00
/* If the mode is at the start of the list, move the start of the list */
if (*modeList == mode)
*modeList = mode->next;
2003-11-14 17:48:57 +01:00
/* If mode is the only one on the list, set the list to NULL */
if ((mode == mode->prev) && (mode == mode->next)) {
*modeList = NULL;
}
else {
if ((mode->prev != NULL) && (mode->prev->next == mode))
mode->prev->next = mode->next;
if ((mode->next != NULL) && (mode->next->prev == mode))
mode->next->prev = mode->prev;
2003-11-14 17:48:57 +01:00
}
free((void *) mode->name);
free(mode);
2003-11-14 17:48:57 +01:00
}
/*
* xf86PruneDriverModes
*
* Remove modes from the driver's mode list which have been marked as
* invalid.
*/
void
2003-11-14 17:48:57 +01:00
xf86PruneDriverModes(ScrnInfoPtr scrp)
{
DisplayModePtr first, p, n;
p = scrp->modes;
if (p == NULL)
return;
2003-11-14 17:48:57 +01:00
do {
if (!(first = scrp->modes))
return;
n = p->next;
if (p->status != MODE_OK) {
xf86DeleteMode(&(scrp->modes), p);
}
p = n;
2003-11-14 17:48:57 +01:00
} while (p != NULL && p != first);
/* modePool is no longer needed, turf it */
while (scrp->modePool) {
/*
* A modePool mode's prev field is used to hold a pointer to the
* member of the scrp->modes list for which a match was considered.
* Clear that pointer first, otherwise xf86DeleteMode might get
* confused
*/
scrp->modePool->prev = NULL;
xf86DeleteMode(&scrp->modePool, scrp->modePool);
}
2003-11-14 17:48:57 +01:00
}
/*
* xf86SetCrtcForModes
*
* Goes through the screen's mode list, and initialises the Crtc
* parameters for each mode. The initialisation includes adjustments
* for interlaced and double scan modes.
*/
void
2003-11-14 17:48:57 +01:00
xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)
{
DisplayModePtr p;
/*
* Store adjustFlags for use with the VidMode extension. There is an
* implicit assumption here that SetCrtcForModes is called once.
*/
scrp->adjustFlags = adjustFlags;
p = scrp->modes;
if (p == NULL)
return;
2003-11-14 17:48:57 +01:00
do {
xf86SetModeCrtc(p, adjustFlags);
DebugF("%sMode %s: %d (%d) %d %d (%d) %d %d (%d) %d %d (%d) %d\n",
(p->type & M_T_DEFAULT) ? "Default " : "",
p->name, p->CrtcHDisplay, p->CrtcHBlankStart,
p->CrtcHSyncStart, p->CrtcHSyncEnd, p->CrtcHBlankEnd,
p->CrtcHTotal, p->CrtcVDisplay, p->CrtcVBlankStart,
p->CrtcVSyncStart, p->CrtcVSyncEnd, p->CrtcVBlankEnd,
p->CrtcVTotal);
p = p->next;
2003-11-14 17:48:57 +01:00
} while (p != NULL && p != scrp->modes);
}
void
2003-11-14 17:48:57 +01:00
xf86PrintModes(ScrnInfoPtr scrp)
{
DisplayModePtr p;
float hsync, refresh = 0;
const char *desc, *desc2, *prefix, *uprefix;
2003-11-14 17:48:57 +01:00
if (scrp == NULL)
return;
2003-11-14 17:48:57 +01:00
xf86DrvMsg(scrp->scrnIndex, X_INFO, "Virtual size is %dx%d (pitch %d)\n",
scrp->virtualX, scrp->virtualY, scrp->displayWidth);
2003-11-14 17:48:57 +01:00
p = scrp->modes;
if (p == NULL)
return;
2003-11-14 17:48:57 +01:00
do {
desc = desc2 = "";
hsync = xf86ModeHSync(p);
refresh = xf86ModeVRefresh(p);
if (p->Flags & V_INTERLACE) {
desc = " (I)";
}
if (p->Flags & V_DBLSCAN) {
desc = " (D)";
}
if (p->VScan > 1) {
desc2 = " (VScan)";
}
if (p->type & M_T_BUILTIN)
prefix = "Built-in mode";
else if (p->type & M_T_DEFAULT)
prefix = "Default mode";
else if (p->type & M_T_DRIVER)
prefix = "Driver mode";
else
prefix = "Mode";
if (p->type & M_T_USERDEF)
uprefix = "*";
else
uprefix = " ";
if (hsync == 0 || refresh == 0) {
if (p->name)
xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
"%s%s \"%s\"\n", uprefix, prefix, p->name);
else
xf86DrvMsg(scrp->scrnIndex, X_PROBED,
"%s%s %dx%d (unnamed)\n",
uprefix, prefix, p->HDisplay, p->VDisplay);
}
else if (p->Clock == p->SynthClock) {
xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
"%s%s \"%s\": %.1f MHz, %.1f kHz, %.1f Hz%s%s\n",
uprefix, prefix, p->name, p->Clock / 1000.0,
hsync, refresh, desc, desc2);
}
else {
xf86DrvMsg(scrp->scrnIndex, X_CONFIG,
"%s%s \"%s\": %.1f MHz (scaled from %.1f MHz), "
"%.1f kHz, %.1f Hz%s%s\n",
uprefix, prefix, p->name, p->Clock / 1000.0,
p->SynthClock / 1000.0, hsync, refresh, desc, desc2);
}
if (hsync != 0 && refresh != 0)
xf86PrintModeline(scrp->scrnIndex, p);
p = p->next;
2003-11-14 17:48:57 +01:00
} while (p != NULL && p != scrp->modes);
}