diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/radeon.h | 3 | ||||
-rw-r--r-- | src/radeon_driver.c | 42 | ||||
-rw-r--r-- | src/radeon_modes.c | 32 | ||||
-rw-r--r-- | src/radeon_probe.h | 12 | ||||
-rw-r--r-- | src/radeon_randr.c | 823 |
6 files changed, 892 insertions, 23 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e0ed9ed7..459a9aef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -82,7 +82,8 @@ radeon_drv_la_SOURCES = \ radeon_accel.c radeon_mergedfb.c radeon_cursor.c radeon_dga.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ radeon_vip.c radeon_misc.c radeon_display.c radeon_modes.c \ - radeon_xf86Modes.c $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) + radeon_xf86Modes.c radeon_randr.c \ + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) theatre_detect_drv_la_LTLIBRARIES = theatre_detect_drv.la theatre_detect_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/radeon.h b/src/radeon.h index 46eedbb9..f6a02275 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -817,6 +817,7 @@ typedef struct { CARD32 tv_dac_adj; + CreateScreenResourcesProcPtr CreateScreenResources; } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -911,7 +912,7 @@ extern RADEONConnector *RADEONGetCrtcConnector(ScrnInfoPtr pScrn, int crtc_num); extern int RADEONValidateMergeModes(ScrnInfoPtr pScrn); extern int RADEONValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName, RADEONMonitorType DisplayType, int crtc2); -extern int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr modeList); +extern int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr *modeList); extern void RADEONSetPitch (ScrnInfoPtr pScrn); diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 2dfcada1..ccd0e1b6 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -439,6 +439,22 @@ struct RADEONInt10Save { static Bool RADEONMapMMIO(ScrnInfoPtr pScrn); static Bool RADEONUnmapMMIO(ScrnInfoPtr pScrn); +static Bool +RADEONCreateScreenResources (ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + pScreen->CreateScreenResources = info->CreateScreenResources; + if (!(*pScreen->CreateScreenResources)(pScreen)) + return FALSE; + + if (!RADEONRandRCreateScreenResources(pScreen)) + return FALSE; + + return TRUE; +} + RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn) { DevUnion *pPriv; @@ -2211,7 +2227,7 @@ static Bool RADEONPreInitModes(ScrnInfoPtr pScrn, xf86Int10InfoPtr pInt10) info->FbMapSize, LOOKUP_BEST_REFRESH); else if (!info->IsSecondary) - modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes, pScrn->monitor->Modes); + modesFound = RADEONValidateFPModes(pScrn, pScrn->display->modes, &pScrn->monitor->Modes); } } @@ -3208,11 +3224,8 @@ _X_EXPORT Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitGamma(pScrn)) goto fail; -#if 0 - if (!RADEONPreInitModes(pScrn, pInt10)) goto fail; -#else - RADEONValidateXF86ModeList(pScrn, TRUE); -#endif + if (!RADEONRandRPreInit(pScrn)) + goto fail; if (!RADEONPreInitCursor(pScrn)) goto fail; @@ -4243,6 +4256,15 @@ _X_EXPORT Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = RADEONBlockHandler; + /* Rotation */ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandR enabled, ignore the following RandR disabled message.\n"); + xf86DisableRandR(); /* Disable built-in RandR extension */ + /* support all rotations */ + RADEONRandRInit(pScreen, RR_Rotate_0); /* only 0 degrees for Radeon */ + + info->CreateScreenResources = pScreen->CreateScreenResources; + pScreen->CreateScreenResources = RADEONCreateScreenResources; + /* Note unused options */ if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); @@ -7036,6 +7058,14 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) return; } +#if RANDR_12_INTERFACE + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "MergedFB does not work with Randr 1.2\n"); + info->MergedFB = FALSE; + return; +#endif + + /* collect MergedFB options */ info->MergedFB = TRUE; info->UseRADEONXinerama = TRUE; diff --git a/src/radeon_modes.c b/src/radeon_modes.c index 694b2ed5..c70f5e02 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -42,10 +42,12 @@ #include "xf86.h" /* Driver data structures */ +#include "randrstr.h" +#include "radeon_probe.h" #include "radeon.h" #include "radeon_reg.h" #include "radeon_macros.h" -#include "radeon_probe.h" + #include "radeon_version.h" #include "radeon_xf86Modes.h" @@ -293,7 +295,7 @@ static DisplayModePtr RADEONFPNativeMode(ScrnInfoPtr pScrn) /* FP mode initialization routine for using on-chip RMX to scale */ -int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr modeList) +int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr *modeList) { RADEONInfoPtr info = RADEONPTR(pScrn); DisplayModePtr last = NULL; @@ -376,7 +378,7 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr m } /* add in all default vesa modes smaller than panel size, used for randr*/ - for (p = modeList; p && p->next; p = p->next->next) { + for (p = *modeList; p && p->next; p = p->next->next) { if ((p->HDisplay <= info->PanelXRes) && (p->VDisplay <= info->PanelYRes)) { tmp = first; while (tmp) { @@ -416,9 +418,9 @@ int RADEONValidateFPModes(ScrnInfoPtr pScrn, char **ppModeName, DisplayModePtr m /* Close the doubly-linked mode list, if we found any usable modes */ if (last) { - last->next = first; - first->prev = last; - pScrn->modes = first; + last->next = NULL; //first; + first->prev = NULL; //last; + *modeList = first; RADEONSetPitch(pScrn); } @@ -597,14 +599,18 @@ RADEONProbeOutputModes(ScrnInfoPtr pScrn) RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); int i; DisplayModePtr ddc_modes, mode; - + DisplayModePtr test; for (i = 0; i < RADEON_MAX_CONNECTOR; i++) { - while(pRADEONEnt->PortInfo[i]->probed_modes != NULL) { - xf86DeleteMode(&pRADEONEnt->PortInfo[i]->probed_modes, - pRADEONEnt->PortInfo[i]->probed_modes); + test = pRADEONEnt->PortInfo[i]->probed_modes; + while(test != NULL) { + xf86DeleteMode(&test, test); } + + pRADEONEnt->PortInfo[i]->probed_modes = test; + /* force reprobe */ + pRADEONEnt->PortInfo[i]->MonType = MT_UNKNOWN; RADEONConnectorFindMonitor(pScrn, i); @@ -655,7 +661,7 @@ RADEONProbeOutputModes(ScrnInfoPtr pScrn) break; case MT_LCD: - RADEONValidateFPModes(pScrn, pScrn->display->modes, pRADEONEnt->PortInfo[i]->probed_modes); + RADEONValidateFPModes(pScrn, pScrn->display->modes, &pRADEONEnt->PortInfo[i]->probed_modes); break; default: break; @@ -695,7 +701,7 @@ RADEONProbeOutputModes(ScrnInfoPtr pScrn) * * This should be obsoleted by RandR 1.2 hopefully. */ -static void +void RADEON_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -769,7 +775,7 @@ RADEON_set_xf86_modes_from_outputs(ScrnInfoPtr pScrn) * Takes the output mode lists and decides the default root window size * and framebuffer pitch. */ -static void +void RADEON_set_default_screen_size(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); diff --git a/src/radeon_probe.h b/src/radeon_probe.h index 7ec5e65e..ebd4babe 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -38,6 +38,7 @@ #include "xf86str.h" #include "xf86DDC.h" +#include "randrstr.h" #define _XF86MISC_SERVER_ #include <X11/extensions/xf86misc.h> @@ -111,6 +112,10 @@ typedef struct Bool IsActive; int binding; // which instance of the driver "owns" this controller DisplayModePtr pCurMode; + +#ifdef RANDR_12_INTERFACE + RRCrtcPtr randr_crtc; +#endif } RADEONController; typedef struct @@ -125,8 +130,11 @@ typedef struct /* one connector can be bound to one CRTC */ int crtc_num; - /* a list of probed modes on this connector */ - DisplayModePtr probed_modes; + /* a list of probed modes on this connector */ + DisplayModePtr probed_modes; +#ifdef RANDR_12_INTERFACE + RROutputPtr randr_output; +#endif } RADEONConnector; diff --git a/src/radeon_randr.c b/src/radeon_randr.c new file mode 100644 index 00000000..2fc012ad --- /dev/null +++ b/src/radeon_randr.c @@ -0,0 +1,823 @@ +/* + * Copyright 2006 Dave Airlie + * + * All Rights Reserved. + * + * 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 on 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 + * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS AND/OR + * THEIR SUPPLIERS 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. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include <stdio.h> + +/* X and server generic header files */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "fbdevhw.h" +#include "vgaHW.h" + +#include "randrstr.h" + +/* Driver data structures */ +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_macros.h" +#include "radeon_probe.h" +#include "radeon_version.h" +#include "radeon_mergedfb.h" + +typedef struct _radeonRandRInfo { + int virtualX; + int virtualY; + int mmWidth; + int mmHeight; + int maxX; + int maxY; + Rotation rotation; /* current mode */ + Rotation supported_rotations; /* driver supported */ +#ifdef RANDR_12_INTERFACE + DisplayModePtr modes[2]; +#endif +} XF86RandRInfoRec, *XF86RandRInfoPtr; + +#ifdef RANDR_12_INTERFACE +static Bool RADEONRandRInit12 (ScreenPtr pScreen); +static Bool RADEONRandRCreateScreenResources12 (ScreenPtr pScreen); +#endif + + +static int RADEONRandRIndex; +static int RADEONRandRGeneration; + +#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) (p)->devPrivates[RADEONRandRIndex].ptr) + +#if RANDR_12_INTERFACE +static void +RADEONRandRPointerMoved (int scrnIndex, int x, int y) +{ +} + +static Bool +RADEONRandRScreenSetSize (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, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); + if (WindowTable[pScreen->myNum]) + RRScreenSizeNotify (pScreen); + return ret; +} + +static Bool +RADEONRandRCrtcNotify (RRCrtcPtr crtc) +{ + ScreenPtr pScreen = crtc->pScreen; + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RRModePtr mode = NULL; + int i, j; + int numOutputs = 0; + int x, y; + int rotation = RR_Rotate_0; + RROutputPtr outputs[RADEON_MAX_CRTC]; + RROutputPtr rrout; + + for (i = 0; i<RADEON_MAX_CONNECTOR; i++) { + + rrout = pRADEONEnt->PortInfo[i]->randr_output; + + outputs[numOutputs++] = rrout; + for (j = 0; j<rrout->numModes; j++) { + DisplayModePtr outMode = rrout->modes[j]->devPrivate; + mode = rrout->modes[j]; + } + } + + return RRCrtcNotify (crtc, mode, x, y, rotation, numOutputs, outputs); +} + +static Bool +RADEONRandRCrtcSet (ScreenPtr pScreen, + RRCrtcPtr crtc, + RRModePtr mode, + int x, + int y, + Rotation rotation, + int num_randr_outputs, + RROutputPtr *randr_outputs) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + + return RADEONRandRCrtcNotify(crtc); +} + + +static Bool +RADEONRandRCrtcSetGamma (ScreenPtr pScreen, + RRCrtcPtr crtc) +{ + return FALSE; +} + +/** + * Given a list of xf86 modes and a RandR Output object, construct + * RandR modes and assign them to the output + */ +static Bool +RADEONxf86RROutputSetModes (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); + rrmode->devPrivate = mode; + if (rrmode) { + 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 +RADEONRandRSetInfo12 (ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RROutputPtr clones[RADEON_MAX_CONNECTOR]; + RRCrtcPtr crtc; + int nclone; + RRCrtcPtr crtcs[RADEON_MAX_CRTC]; + int ncrtc; + DisplayModePtr modes, mode; + xRRModeInfo modeInfo; + RRModePtr rrmode, *rrmodes; + int nmode, npreferred; + int i, j, p; + CARD32 possibleOptions = 0; + CARD32 currentOptions = 0; + int connection; + int subpixel = SubPixelNone; + RRCrtcPtr randr_crtc; + RADEONConnector *connector; + + for (i = 0; i < RADEON_MAX_CONNECTOR; i++) { + ncrtc = 0; + crtc = NULL; + + connector = pRADEONEnt->PortInfo[i]; + + if (connector->MonType) { + crtc = pRADEONEnt->Controller[i]->randr_crtc; + crtcs[ncrtc++] = crtc; + randr_crtc = crtc; + } else + randr_crtc = NULL; + + + if (!RROutputSetCrtcs(connector->randr_output, crtcs, ncrtc)) + return FALSE; + + RROutputSetCrtc(connector->randr_output, crtc); + + nmode = 0; + npreferred = 0; + rrmodes = NULL; + + if (connector->probed_modes) { + RADEONxf86RROutputSetModes (connector->randr_output, connector->probed_modes); + } + + connection = RR_Disconnected; + if (connector->MonType > MT_NONE) + connection = RR_Connected; + + RROutputSetConnection(connector->randr_output, connection); + + RROutputSetSubpixelOrder(connector->randr_output, subpixel); + } + return TRUE; +} + +/* + * Query the hardware for the current state, then mirror + * that to RandR + */ +static Bool +RADEONRandRGetInfo12 (ScreenPtr pScreen, Rotation *rotations) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + + RADEONProbeOutputModes(pScrn); + return RADEONRandRSetInfo12 (pScrn); +} + +extern const char *ConnectorTypeName[], *ConnectorTypeNameATOM[]; + +Bool +RADEONRandRCreateScreenResources (ScreenPtr pScreen) +{ +#if RANDR_12_INTERFACE + if (RADEONRandRCreateScreenResources12 (pScreen)) + return TRUE; +#endif + return FALSE; +} + +static Bool +RADEONRandRCreateObjects12(ScrnInfoPtr pScrn) +{ + int i; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!RRInit()) + return FALSE; + + /* + * Create RandR resources, then probe them + */ + for (i = 0; i < 2; i++) + { + RRCrtcPtr randr_crtc = RRCrtcCreate((void *)i); + + if (!randr_crtc) + return FALSE; + + RRCrtcGammaSetSize(randr_crtc, 256); + pRADEONEnt->Controller[i]->randr_crtc = randr_crtc; + } + + for (i = 0; i < 2; i++) + { + int output = pRADEONEnt->PortInfo[i]->ConnectorType; + const char *name = name = info->IsAtomBios ? ConnectorTypeNameATOM[output] : ConnectorTypeName[output]; + RROutputPtr randr_output = RROutputCreate(name, strlen(name), + (void *) i); + + if (!randr_output) + return FALSE; + + pRADEONEnt->PortInfo[i]->randr_output = randr_output; + } + return TRUE; +} + +static Bool +RADEONRandRCreateScreenResources12 (ScreenPtr pScreen) +{ + XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + DisplayModePtr mode; + const char *name; + int i; + + for (i = 0; i < 2; i++) + { + if (!RRCrtcAttachScreen(pRADEONEnt->Controller[i]->randr_crtc, pScreen)) + return FALSE; + } + + for (i = 0; i < 2; i++) { + if (!RROutputAttachScreen(pRADEONEnt->PortInfo[i]->randr_output, pScreen)) + return FALSE; + } + + mode = pScrn->currentMode; + if (mode) { + int mmWidth, mmHeight; + + if (mode->HDisplay == pScreen->width && + mode->VDisplay == pScreen->height) + { + mmWidth = pScrn->widthmm; + mmHeight = pScrn->heightmm; + } else { +#define MMPERINCH 25.4 + mmWidth = (double) mode->HDisplay / pScrn->xDpi * MMPERINCH; + mmHeight = (double) mode->VDisplay / pScrn->yDpi * MMPERINCH; + } + RADEONRandRScreenSetSize (pScreen, + mode->HDisplay, + mode->VDisplay, + mmWidth, + mmHeight); + } + + for (i = 0; i < RADEON_MAX_CRTC; i++) + RADEONRandRCrtcNotify (pRADEONEnt->Controller[i]->randr_crtc); + + if (randrp->virtualX == -1 || randrp->virtualY == -1) + { + randrp->virtualX = pScrn->virtualX; + randrp->virtualY = pScrn->virtualY; + } + + RRScreenSetSizeRange (pScreen, 320, 240, + randrp->virtualX, randrp->virtualY); + return TRUE; + +} + +Bool +RADEONRandRInit (ScreenPtr pScreen, int rotation) +{ + rrScrPrivPtr rp; + XF86RandRInfoPtr randrp; + +#ifdef PANORAMIX + /* XXX disable RandR when using Xinerama */ + if (!noPanoramiXExtension) + return TRUE; +#endif + if (RADEONRandRGeneration != serverGeneration) + { + RADEONRandRIndex = AllocateScreenPrivateIndex(); + RADEONRandRGeneration = serverGeneration; + } + + randrp = xalloc (sizeof (XF86RandRInfoRec)); + if (!randrp) + return FALSE; + + if (!RRScreenInit(pScreen)) + { + xfree (randrp); + return FALSE; + } + rp = rrGetScrPriv(pScreen); + // rp->rrGetInfo = RADEONRandRGetInfo; + // rp->rrSetConfig = RADEONRandRSetConfig; + + 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 = rotation; + + randrp->maxX = randrp->maxY = 0; + + pScreen->devPrivates[RADEONRandRIndex].ptr = randrp; + +#if RANDR_12_INTERFACE + if (!RADEONRandRInit12 (pScreen)) + return FALSE; +#endif + return TRUE; +} + +static Bool +RADEONRandRInit12(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + + rp->rrGetInfo = RADEONRandRGetInfo12; + rp->rrScreenSetSize = RADEONRandRScreenSetSize; + rp->rrCrtcSet = RADEONRandRCrtcSet; + rp->rrCrtcSetGamma = RADEONRandRCrtcSetGamma; + rp->rrSetConfig = NULL; + // memset (rp->modes, '\0', sizeof (rp->modes)); + pScrn->PointerMoved = RADEONRandRPointerMoved; + return TRUE; +} + +static RRModePtr +RADEONRRDefaultMode (RROutputPtr output) +{ + RRModePtr target_mode = NULL; + int target_diff = 0; + int mmHeight; + int num_modes; + int m; + + num_modes = output->numPreferred ? output->numPreferred : output->numModes; + mmHeight = output->mmHeight; + if (!mmHeight) + mmHeight = 203; /* 768 pixels at 96dpi */ + /* + * Pick a mode closest to 96dpi + */ + for (m = 0; m < num_modes; m++) + { + RRModePtr mode = output->modes[m]; + int dpi; + int diff; + + dpi = (mode->mode.height * 254) / (mmHeight * 10); + diff = dpi - 96; + diff = diff < 0 ? -diff : diff; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static RRModePtr +RADEONClosestMode (RROutputPtr output, RRModePtr match) +{ + RRModePtr target_mode = NULL; + int target_diff = 0; + int m; + + /* + * Pick a mode closest to the specified mode + */ + for (m = 0; m < output->numModes; m++) + { + RRModePtr mode = output->modes[m]; + int dx, dy; + int diff; + + /* exact matches are preferred */ + if (mode == match) + return mode; + + dx = match->mode.width - mode->mode.width; + dy = match->mode.height - mode->mode.height; + diff = dx * dx + dy * dy; + if (target_mode == NULL || diff < target_diff) + { + target_mode = mode; + target_diff = diff; + } + } + return target_mode; +} + +static int +RADEONRRPickCrtcs (RROutputPtr *outputs, + RRCrtcPtr *best_crtcs, + RRModePtr *modes, + int num_outputs, + int n) +{ + int c, o, l; + RROutputPtr output; + RRCrtcPtr crtc; + RRCrtcPtr *crtcs; + RRCrtcPtr best_crtc; + int best_score; + int score; + int my_score; + + if (n == num_outputs) + return 0; + output = outputs[n]; + + /* + * Compute score with this output disabled + */ + best_crtcs[n] = NULL; + best_crtc = NULL; + best_score = RADEONRRPickCrtcs (outputs, best_crtcs, modes, num_outputs, n+1); + if (modes[n] == NULL) + return best_score; + + crtcs = xalloc (num_outputs * sizeof (RRCrtcPtr)); + if (!crtcs) + return best_score; + + my_score = 1; + /* Score outputs that are known to be connected higher */ + if (output->connection == RR_Connected) + my_score++; + /* Score outputs with preferred modes higher */ + if (output->numPreferred) + my_score++; + /* + * Select a crtc for this output and + * then attempt to configure the remaining + * outputs + */ + for (c = 0; c < output->numCrtcs; c++) + { + crtc = output->crtcs[c]; + /* + * Check to see if some other output is + * using this crtc + */ + for (o = 0; o < n; o++) + if (best_crtcs[o] == crtc) + break; + if (o < n) + { + /* + * If the two outputs desire the same mode, + * see if they can be cloned + */ + if (modes[o] == modes[n]) + { + for (l = 0; l < output->numClones; l++) + if (output->clones[l] == outputs[o]) + break; + if (l == output->numClones) + continue; /* nope, try next CRTC */ + } + else + continue; /* different modes, can't clone */ + } + crtcs[n] = crtc; + memcpy (crtcs, best_crtcs, n * sizeof (RRCrtcPtr)); + score = my_score + RADEONRRPickCrtcs (outputs, crtcs, modes, + num_outputs, n+1); + if (score >= best_score) + { + best_crtc = crtc; + best_score = score; + memcpy (best_crtcs, crtcs, num_outputs * sizeof (RRCrtcPtr)); + } + } + xfree (crtcs); + return best_score; +} + +static Bool +RADEONRRInitialConfiguration (RROutputPtr *outputs, + RRCrtcPtr *crtcs, + RRModePtr *modes, + int num_outputs) +{ + int o; + RRModePtr target_mode = NULL; + + for (o = 0; o < num_outputs; o++) + modes[o] = NULL; + + /* + * Let outputs with preferred modes drive screen size + */ + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + if (output->connection != RR_Disconnected && output->numPreferred) + { + target_mode = RADEONRRDefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + break; + } + } + } + if (!target_mode) + { + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + if (output->connection != RR_Disconnected) + { + target_mode = RADEONRRDefaultMode (output); + if (target_mode) + { + modes[o] = target_mode; + break; + } + } + } + } + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + if (output->connection != RR_Disconnected && !modes[o]) + modes[o] = RADEONClosestMode (output, target_mode); + } + + if (!RADEONRRPickCrtcs (outputs, crtcs, modes, num_outputs, 0)) + return FALSE; + + return TRUE; +} + +/* + * Compute the virtual size necessary to place all of the available + * crtcs in a panorama configuration + */ + +static void +RADEONRRDefaultScreenLimits (RROutputPtr *outputs, int num_outputs, + RRCrtcPtr *crtcs, int num_crtc, + int *widthp, int *heightp) +{ + int width = 0, height = 0; + int o; + int c; + int m; + int s; + + for (c = 0; c < num_crtc; c++) + { + RRCrtcPtr crtc = crtcs[c]; + int crtc_width = 1600, crtc_height = 1200; + + for (o = 0; o < num_outputs; o++) + { + RROutputPtr output = outputs[o]; + + for (s = 0; s < output->numCrtcs; s++) + if (output->crtcs[s] == crtc) + break; + if (s == output->numCrtcs) + continue; + for (m = 0; m < output->numModes; m++) + { + RRModePtr mode = output->modes[m]; + if (mode->mode.width > crtc_width) + crtc_width = mode->mode.width; + if (mode->mode.height > crtc_width) + crtc_height = mode->mode.height; + } + } + width += crtc_width; + if (crtc_height > height) + height = crtc_height; + } + *widthp = width; + *heightp = height; +} + + +Bool +RADEONRandRPreInit(ScrnInfoPtr pScrn) +{ + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); +#if RANDR_12_INTERFACE + RROutputPtr outputs[RADEON_MAX_CONNECTOR]; + RRCrtcPtr output_crtcs[RADEON_MAX_CONNECTOR]; + RRModePtr output_modes[RADEON_MAX_CONNECTOR]; + RRCrtcPtr crtcs[RADEON_MAX_CRTC]; +#endif + int conn, crtc; + int o,c; + int width, height; + + RADEONProbeOutputModes(pScrn); + +#if RANDR_12_INTERFACE + if (!RADEONRandRCreateObjects12(pScrn)) + return FALSE; + + if (!RADEONRandRSetInfo12(pScrn)) + return FALSE; + +#endif + + /* + * With RandR info set up, let RandR choose + * the initial configuration + */ + for (o = 0; o < RADEON_MAX_CONNECTOR; o++) + outputs[o] = pRADEONEnt->PortInfo[o]->randr_output; + for (c = 0; c < RADEON_MAX_CRTC; c++) + crtcs[c] = pRADEONEnt->Controller[c]->randr_crtc; + + if (!RADEONRRInitialConfiguration (outputs, output_crtcs, output_modes, + RADEON_MAX_CONNECTOR)) + return FALSE; + + RADEONRRDefaultScreenLimits (outputs, RADEON_MAX_CONNECTOR, + crtcs, RADEON_MAX_CRTC, + &width, &height); + + if (width > pScrn->virtualX) + pScrn->virtualX = width; + if (height > pScrn->virtualY) + pScrn->virtualY = height; + + for (o = 0; o < RADEON_MAX_CONNECTOR; o++) + { + RRModePtr randr_mode = output_modes[o]; + DisplayModePtr mode; + RRCrtcPtr randr_crtc = output_crtcs[o]; + int pipe; + Bool enabled; + + if (randr_mode) + mode = (DisplayModePtr) randr_mode->devPrivate; + else + mode = NULL; + if (randr_crtc) + { + pipe = (int) randr_crtc->devPrivate; + enabled = TRUE; + } + else + { + pipe = 0; + enabled = FALSE; + } + // if (mode) + // pRADEON->pipes[pipe].desiredMode = *mode; + // pRADEON->output[o].pipe = pipe; + // pRADEON->output[o].enabled = enabled; + } + + RADEON_set_xf86_modes_from_outputs(pScrn); + RADEON_set_default_screen_size(pScrn); + + return TRUE; +} +#endif |