diff options
-rw-r--r-- | man/radeon.man | 28 | ||||
-rw-r--r-- | src/radeon.h | 9 | ||||
-rw-r--r-- | src/radeon_driver.c | 96 | ||||
-rw-r--r-- | src/radeon_mergedfb.c | 824 | ||||
-rw-r--r-- | src/radeon_mergedfb.h | 4 |
5 files changed, 723 insertions, 238 deletions
diff --git a/man/radeon.man b/man/radeon.man index 2dad96b..6cca630 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -349,6 +349,16 @@ Set the relationship of CRT2 relative to CRT1. Valid options are: .br For example, Option "CRT2Position" "RightOf" .br +This option also supports an offset. This is most useful when +.B MergedNonRectangular +is enabled. For example if you want CRT2 to be offset 100 pixels down from +the start of CRT1, you'd type: +.br +Option "CRT2Position" "LeftOf 100" +.br +The offset is vertical for LeftOf and RightOf and horizontal for Above and +Below. Offsets can be postive or negative. +.br The default value is .B Clone. .TP @@ -383,7 +393,7 @@ Force hardware overlay to clone head. The default value is .B off. .TP -.BI "Option \*qNoMergedXinerama\*q \*q" boolean \*q +.BI "Option \*qMergedXinerama\*q \*q" boolean \*q Since merged framebuffer mode does not use Xinerama, apps are not able to intelligently place windows. Merged framebuffer mode provides its own pseudo-Xinerama. This allows Xinerama compliant applications to place windows appropriately. There are some caveats. @@ -397,7 +407,7 @@ three heads), pseudo-Xinerama will be disabled. This option allows you turn off the driver provided pseudo-Xinerama extension. .br The default value is -.B FALSE. +.B TRUE. .TP .BI "Option \*qMergedXineramaCRT2IsScreen0\*q \*q" boolean \*q By default the pseudo-Xinerama provided by the driver makes the left-most or bottom @@ -417,6 +427,15 @@ For example, Option "MergedDPI" "100 100" The default value is .B undefined. .TP +.BI "Option \*qMergedNonRectangular\*q \*q" boolean \*q +If you are using MergedFB with two modes of different sizes, turn this option on to +keep the smaller head from scrolling within the larger virtual desktop and to keep +the mouse from moving into that area. Applications that are not Xinerama aware can +potentially end up stranded in this area. +.br +The default value is +.B FALSE. +.TP .BI "Option \*qColorTiling\*q \*q" "boolean" \*q Frame buffer can be addressed either in linear or tiled mode. Tiled mode can provide significant performance benefits with 3D applications, for 2D it shouldn't matter @@ -461,11 +480,6 @@ The default value is Enable page flipping for 3D acceleration. This will increase performance but not work correctly in some rare cases, hence the default is .B off. -.br -.B Note: -Page flipping does not work well in certain configurations with MergedFB. If you -see rendering errors or other strange behavior, disable page flipping. - .TP .BI "Option \*qForceMinDotClock\*q \*q" frequency \*q Override minimum dot clock. Some Radeon BIOSes report a minimum dot diff --git a/src/radeon.h b/src/radeon.h index a99e7cd..593baf2 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -87,6 +87,10 @@ typedef enum { radeonClone } RADEONScrn2Rel; +typedef struct _region { + int x0,x1,y0,y1; +} region; + /* ------------------------------------- */ #define RADEON_DEBUG 0 /* Turn off debugging output */ @@ -237,6 +241,7 @@ typedef struct { int bitsPerPixel; int depth; int displayWidth; + int displayHeight; int pixel_code; int pixel_bytes; DisplayModePtr mode; @@ -636,6 +641,10 @@ typedef struct { Bool AtLeastOneNonClone; int MergedFBXDPI, MergedFBYDPI; Bool NoVirtual; + int CRT1XOffs, CRT1YOffs, CRT2XOffs, CRT2YOffs; + int MBXNR1XMAX, MBXNR1YMAX, MBXNR2XMAX, MBXNR2YMAX; + Bool NonRect, HaveNonRect, HaveOffsRegions, MouseRestrictions; + region NonRectDead, OffDead1, OffDead2; /* special handlings for DELL triple-head server */ Bool IsDellServer; diff --git a/src/radeon_driver.c b/src/radeon_driver.c index 5b078b9..77a14da 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -156,8 +156,10 @@ typedef enum { OPTION_CRT2POS, OPTION_METAMODES, OPTION_MERGEDDPI, - OPTION_NORADEONXINERAMA, + OPTION_RADEONXINERAMA, OPTION_CRT2ISSCRN0, + OPTION_MERGEDFBNONRECT, + OPTION_MERGEDFBMOUSER, OPTION_DISP_PRIORITY, OPTION_PANEL_SIZE, OPTION_MIN_DOTCLOCK, @@ -215,8 +217,10 @@ static const OptionInfoRec RADEONOptions[] = { { OPTION_CRT2POS, "CRT2Position", OPTV_ANYSTR, {0}, FALSE }, { OPTION_METAMODES, "MetaModes", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MERGEDDPI, "MergedDPI", OPTV_ANYSTR, {0}, FALSE }, - { OPTION_NORADEONXINERAMA, "NoMergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_RADEONXINERAMA, "MergedXinerama", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRT2ISSCRN0, "MergedXineramaCRT2IsScreen0", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MERGEDFBNONRECT, "MergedNonRectangular", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_MERGEDFBMOUSER, "MergedMouseRestriction", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DISP_PRIORITY, "DisplayPriority", OPTV_ANYSTR, {0}, FALSE }, { OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE }, { OPTION_MIN_DOTCLOCK, "ForceMinDotClock", OPTV_FREQ, {0}, FALSE }, @@ -5574,6 +5578,8 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if(info->UseRADEONXinerama) { RADEONnoPanoramiXExtension = FALSE; RADEONXineramaExtensionInit(pScrn); + } else { + info->MouseRestrictions = FALSE; } } @@ -8562,6 +8568,10 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) info->CRT2IsScrn0 = FALSE; info->CRT2Position = radeonClone; info->MergedFBXDPI = info->MergedFBYDPI = 0; + info->CRT1XOffs = info->CRT1YOffs = info->CRT2XOffs = info->CRT2YOffs = 0; + info->NonRect = info->HaveNonRect = info->HaveOffsRegions = FALSE; + info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; + info->MouseRestrictions = TRUE; if (info->MergeType == MT_NONE) { info->MergedFB = FALSE; @@ -8597,36 +8607,60 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) } } if(info->MergedFB) { + int result, ival; + Bool valid = FALSE; + char *tempstr; strptr = (char *)xf86GetOptValString(info->Options, OPTION_CRT2POS); - if(strptr) { - if((!strcmp(strptr,"LeftOf")) || (!strcmp(strptr,"leftof"))) { - info->CRT2Position = radeonLeftOf; - info->CRT2IsScrn0 = TRUE; - } - else if((!strcmp(strptr,"RightOf")) || (!strcmp(strptr,"rightof"))) { - info->CRT2Position = radeonRightOf; - info->CRT2IsScrn0 = FALSE; - } - else if((!strcmp(strptr,"Above")) || (!strcmp(strptr,"above"))) { - info->CRT2Position = radeonAbove; - info->CRT2IsScrn0 = FALSE; - } - else if((!strcmp(strptr,"Below")) || (!strcmp(strptr,"below"))) { - info->CRT2Position = radeonBelow; - info->CRT2IsScrn0 = TRUE; - } - else if((!strcmp(strptr,"Clone")) || (!strcmp(strptr,"clone"))) { - info->CRT2Position = radeonClone; - /*info->CRT2IsScrn0 = FALSE; */ - info->CRT2IsScrn0 = TRUE; - } - else { + tempstr = xalloc(strlen(strptr) + 1); + result = sscanf(strptr, "%s %d", tempstr, &ival); + if(result >= 1) { + if(!xf86NameCmp(tempstr,"LeftOf")) { + info->CRT2Position = radeonLeftOf; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1YOffs = -ival; + else info->CRT2YOffs = ival; + } + info->CRT2IsScrn0 = TRUE; + } else if(!xf86NameCmp(tempstr,"RightOf")) { + info->CRT2Position = radeonRightOf; + if(result == 2) { + if(ival < 0) info->CRT1YOffs = -ival; + else info->CRT2YOffs = ival; + } + info->CRT2IsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Above")) { + info->CRT2Position = radeonAbove; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1XOffs = -ival; + else info->CRT2XOffs = ival; + } + info->CRT2IsScrn0 = FALSE; + } else if(!xf86NameCmp(tempstr,"Below")) { + info->CRT2Position = radeonBelow; + valid = TRUE; + if(result == 2) { + if(ival < 0) info->CRT1XOffs = -ival; + else info->CRT2XOffs = ival; + } + info->CRT2IsScrn0 = TRUE; + } else if(!xf86NameCmp(tempstr,"Clone")) { + info->CRT2Position = radeonClone; + if(result == 1) valid = TRUE; + /*info->CRT2IsScrn0 = TRUE;*/ + } + } + if(!valid) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "\"%s\" is not a valid parameter for Option \"CRT2Position\"\n", strptr); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid parameters are \"RightOf\", \"LeftOf\", \"Above\", \"Below\", or \"Clone\"\n"); - } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Except for \"Clone\", the parameter may be followed by an integer.\n"); } + xfree(tempstr); + strptr = (char *)xf86GetOptValString(info->Options, OPTION_METAMODES); if(strptr) { info->MetaModes = xalloc(strlen(strptr) + 1); @@ -8643,8 +8677,8 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) if(info->CRT2VRefresh) memcpy(info->CRT2VRefresh, strptr, strlen(strptr) + 1); } - if(xf86GetOptValBool(info->Options, OPTION_NORADEONXINERAMA, &val)) { - if (val) + if(xf86GetOptValBool(info->Options, OPTION_RADEONXINERAMA, &val)) { + if (!val) info->UseRADEONXinerama = FALSE; } if(info->UseRADEONXinerama) { @@ -8652,6 +8686,12 @@ RADEONGetMergedFBOptions(ScrnInfoPtr pScrn) if(val) info->CRT2IsScrn0 = TRUE; else info->CRT2IsScrn0 = FALSE; } + if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBNONRECT, &val)) { + info->NonRect = val ? TRUE : FALSE; + } + if(xf86GetOptValBool(info->Options, OPTION_MERGEDFBMOUSER, &val)) { + info->MouseRestrictions = val ? TRUE : FALSE; + } } strptr = (char *)xf86GetOptValString(info->Options, OPTION_MERGEDDPI); if(strptr) { diff --git a/src/radeon_mergedfb.c b/src/radeon_mergedfb.c index 94102b9..9193476 100644 --- a/src/radeon_mergedfb.c +++ b/src/radeon_mergedfb.c @@ -286,6 +286,48 @@ RADEONFindWidestTallestMode(DisplayModePtr i, Bool tallest) return d; } +static void +RADEONFindWidestTallestCommonMode(DisplayModePtr i, DisplayModePtr j, Bool tallest, + DisplayModePtr *a, DisplayModePtr *b) +{ + DisplayModePtr c = i, d; + int max = 0; + Bool foundone; + + (*a) = (*b) = NULL; + + if(!i || !j) return; + + do { + d = j; + foundone = FALSE; + do { + if( (c->HDisplay == d->HDisplay) && + (c->VDisplay == d->VDisplay) ) { + foundone = TRUE; + break; + } + d = d->next; + } while(d != j); + if(foundone) { + if(tallest) { + if(c->VDisplay > max) { + max = c->VDisplay; + (*a) = c; + (*b) = d; + } + } else { + if(c->HDisplay > max) { + max = c->HDisplay; + (*a) = c; + (*b) = d; + } + } + } + c = c->next; + } while(c != i); +} + static DisplayModePtr RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, DisplayModePtr i, DisplayModePtr j, @@ -295,43 +337,66 @@ RADEONGenerateModeListFromLargestModes(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); DisplayModePtr mode1 = NULL; DisplayModePtr mode2 = NULL; + DisplayModePtr mode3 = NULL; + DisplayModePtr mode4 = NULL; DisplayModePtr result = NULL; int p = 0; int count = 0; info->AtLeastOneNonClone = FALSE; + /* Now build a default list of MetaModes. + * - Non-clone: If the user enabled NonRectangular, we use the + * largest mode for each CRT1 and CRT2. If not, we use the largest + * common mode for CRT1 and CRT2 (if available). Additionally, and + * regardless if the above, we produce a clone mode consisting of + * the largest common mode (if available) in order to use DGA. + * - Clone: If the (global) CRT2Position is Clone, we use the + * largest common mode if available, otherwise the first two modes + * in each list. + */ switch(srel) { case radeonLeftOf: case radeonRightOf: mode1 = RADEONFindWidestTallestMode(i, FALSE); mode2 = RADEONFindWidestTallestMode(j, FALSE); + RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); break; case radeonAbove: case radeonBelow: mode1 = RADEONFindWidestTallestMode(i, TRUE); mode2 = RADEONFindWidestTallestMode(j, TRUE); + RADEONFindWidestTallestCommonMode(i, j, TRUE, &mode3, &mode4); break; case radeonClone: - mode1 = i; - mode2 = j; - while (pScrn->display->modes[count]) count++; - for (p = 0; p < count; p++) { - result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel); - mode1 = mode1->next; - mode2 = mode2->next; - } + RADEONFindWidestTallestCommonMode(i, j, FALSE, &mode3, &mode4); + if(mode3 && mode4) { + mode1 = mode3; + mode2 = mode4; + } else { + mode1 = i; + mode2 = j; + } + } + + if(srel != radeonClone) { + if(mode3 && mode4 && !info->NonRect) { + mode1 = mode3; + mode2 = mode2; + } } if(mode1 && mode2) { - if (srel == radeonClone) - return result; - else - return(RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel)); - } else { - return NULL; + result = RADEONCopyModeNLink(pScrn, result, mode1, mode2, srel); + } + + if(srel != radeonClone) { + if(mode3 && mode4) { + result = RADEONCopyModeNLink(pScrn, result, mode3, mode4, radeonClone); + } } + return result; } /* Generate the merged-fb mode modelist @@ -452,12 +517,18 @@ RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, DisplayModePtr i, DisplayModePtr j, RADEONScrn2Rel srel) { + RADEONInfoPtr info = RADEONPTR(pScrn); + if(str != NULL) { return(RADEONGenerateModeListFromMetaModes(pScrn, str, i, j, srel)); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No MetaModes given, linking %s modes by default\n", - (srel == radeonClone) ? "first" : "largest"); + "No MetaModes given, linking %s modes by default\n", + (srel == radeonClone) ? "largest common" : + (info->NonRect ? + (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest" : "tallest") + : + (((srel == radeonLeftOf) || (srel == radeonRightOf)) ? "widest common" : "tallest common")) ); return(RADEONGenerateModeListFromLargestModes(pScrn, i, j, srel)); } } @@ -465,30 +536,47 @@ RADEONGenerateModeList(ScrnInfoPtr pScrn, char* str, void RADEONRecalcDefaultVirtualSize(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); DisplayModePtr mode, bmode; - int max; + int maxh, maxv; static const char *str = "MergedFB: Virtual %s %d\n"; + static const char *errstr = "Virtual %s to small for given CRT2Position offset\n"; + + mode = bmode = pScrn->modes; + maxh = maxv = 0; + do { + if(mode->HDisplay > maxh) maxh = mode->HDisplay; + if(mode->VDisplay > maxv) maxv = mode->VDisplay; + mode = mode->next; + } while(mode != bmode); + maxh += info->CRT1XOffs + info->CRT2XOffs; + maxv += info->CRT1YOffs + info->CRT2YOffs; if(!(pScrn->display->virtualX)) { - mode = bmode = pScrn->modes; - max = 0; - do { - if(mode->HDisplay > max) max = mode->HDisplay; - mode = mode->next; - } while(mode != bmode); - pScrn->virtualX = max; - pScrn->displayWidth = max; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", max); + if(maxh > 8191) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Virtual width with CRT2Position offset beyond hardware specs\n"); + info->CRT1XOffs = info->CRT2XOffs = 0; + maxh -= (info->CRT1XOffs + info->CRT2XOffs); + } + pScrn->virtualX = maxh; + pScrn->displayWidth = maxh; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "width", maxh); + } else { + if(maxh < pScrn->display->virtualX) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "width"); + info->CRT1XOffs = info->CRT2XOffs = 0; + } } + if(!(pScrn->display->virtualY)) { - mode = bmode = pScrn->modes; - max = 0; - do { - if(mode->VDisplay > max) max = mode->VDisplay; - mode = mode->next; - } while(mode != bmode); - pScrn->virtualY = max; - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", max); + pScrn->virtualY = maxv; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, str, "height", maxv); + } else { + if(maxv < pScrn->display->virtualY) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, errstr, "height"); + info->CRT1YOffs = info->CRT2YOffs = 0; + } } } @@ -500,8 +588,14 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) ScrnInfoPtr pScrn2 = NULL; int crt1scrnnum = 0, crt2scrnnum = 1; int x1=0, x2=0, y1=0, y2=0, h1=0, h2=0, w1=0, w2=0; + int realvirtX, realvirtY; DisplayModePtr currentMode, firstMode; Bool infochanged = FALSE; + Bool usenonrect = info->NonRect; + const char *rectxine = "\t... setting up rectangular Xinerama layout\n"; + + info->MBXNR1XMAX = info->MBXNR1YMAX = info->MBXNR2XMAX = info->MBXNR2YMAX = 65536; + info->HaveNonRect = info->HaveOffsRegions = FALSE; if(!info->MergedFB) return; @@ -521,6 +615,10 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) * the maxCRT fields here (and not somewhere else, like in CopyNLink) */ + /* "Real" virtual: Virtual without the Offset */ + realvirtX = pScrn1->virtualX - info->CRT1XOffs - info->CRT2XOffs; + realvirtY = pScrn1->virtualY - info->CRT1YOffs - info->CRT2YOffs; + if((info->RADEONXineramaVX != pScrn1->virtualX) || (info->RADEONXineramaVY != pScrn1->virtualY)) { if(!(pScrn1->modes)) { @@ -545,50 +643,59 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) DisplayModePtr j = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2; RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)currentMode->Private)->CRT2Position; - if((i->HDisplay <= pScrn1->virtualX) && (j->HDisplay <= pScrn1->virtualX) && - (i->VDisplay <= pScrn1->virtualY) && (j->VDisplay <= pScrn1->virtualY)) { - - if(srel != radeonClone) { - if(info->maxCRT1_X1 <= i->HDisplay) { - info->maxCRT1_X1 = i->HDisplay; /* Largest CRT1 mode */ - if(info->maxCRT1_X2 < j->HDisplay) { - info->maxCRT1_X2 = j->HDisplay; /* Largest X of CRT2 mode displayed with largest CRT1 mode */ - } - } - if(info->maxCRT2_X2 <= j->HDisplay) { - info->maxCRT2_X2 = j->HDisplay; /* Largest CRT2 mode */ - if(info->maxCRT2_X1 < i->HDisplay) { - info->maxCRT2_X1 = i->HDisplay; /* Largest X of CRT1 mode displayed with largest CRT2 mode */ - } - } - if(info->maxCRT1_Y1 <= i->VDisplay) { - info->maxCRT1_Y1 = i->VDisplay; - if(info->maxCRT1_Y2 < j->VDisplay) { - info->maxCRT1_Y2 = j->VDisplay; - } - } - if(info->maxCRT2_Y2 <= j->VDisplay) { - info->maxCRT2_Y2 = j->VDisplay; - if(info->maxCRT2_Y1 < i->VDisplay) { - info->maxCRT2_Y1 = i->VDisplay; - } - } - } else { - if(info->maxClone_X1 < i->HDisplay) { - info->maxClone_X1 = i->HDisplay; - } - if(info->maxClone_X2 < j->HDisplay) { - info->maxClone_X2 = j->HDisplay; - } - if(info->maxClone_Y1 < i->VDisplay) { - info->maxClone_Y1 = i->VDisplay; - } - if(info->maxClone_Y2 < j->VDisplay) { - info->maxClone_Y2 = j->VDisplay; - } - } - } - currentMode = p; + if((currentMode->HDisplay <= realvirtX) && (currentMode->VDisplay <= realvirtY) && + (i->HDisplay <= realvirtX) && (j->HDisplay <= realvirtX) && + (i->VDisplay <= realvirtY) && (j->VDisplay <= realvirtY)) { + + if(srel != radeonClone) { + if(info->maxCRT1_X1 == i->HDisplay) { + if(info->maxCRT1_X2 < j->HDisplay) { + info->maxCRT1_X2 = j->HDisplay; /* Widest CRT2 mode displayed with widest CRT1 mode */ + } + } else if(info->maxCRT1_X1 < i->HDisplay) { + info->maxCRT1_X1 = i->HDisplay; /* Widest CRT1 mode */ + info->maxCRT1_X2 = j->HDisplay; + } + if(info->maxCRT2_X2 == j->HDisplay) { + if(info->maxCRT2_X1 < i->HDisplay) { + info->maxCRT2_X1 = i->HDisplay; /* Widest CRT1 mode displayed with widest CRT2 mode */ + } + } else if(info->maxCRT2_X2 < j->HDisplay) { + info->maxCRT2_X2 = j->HDisplay; /* Widest CRT2 mode */ + info->maxCRT2_X1 = i->HDisplay; + } + if(info->maxCRT1_Y1 == i->VDisplay) { /* Same as above, but tallest instead of widest */ + if(info->maxCRT1_Y2 < j->VDisplay) { + info->maxCRT1_Y2 = j->VDisplay; + } + } else if(info->maxCRT1_Y1 < i->VDisplay) { + info->maxCRT1_Y1 = i->VDisplay; + info->maxCRT1_Y2 = j->VDisplay; + } + if(info->maxCRT2_Y2 == j->VDisplay) { + if(info->maxCRT2_Y1 < i->VDisplay) { + info->maxCRT2_Y1 = i->VDisplay; + } + } else if(info->maxCRT2_Y2 < j->VDisplay) { + info->maxCRT2_Y2 = j->VDisplay; + info->maxCRT2_Y1 = i->VDisplay; + } + } else { + if(info->maxClone_X1 < i->HDisplay) { + info->maxClone_X1 = i->HDisplay; + } + if(info->maxClone_X2 < j->HDisplay) { + info->maxClone_X2 = j->HDisplay; + } + if(info->maxClone_Y1 < i->VDisplay) { + info->maxClone_Y1 = i->VDisplay; + } + if(info->maxClone_Y2 < j->VDisplay) { + info->maxClone_Y2 = j->VDisplay; + } + } + } + currentMode = p; } while((currentMode) && (currentMode != firstMode)); @@ -598,97 +705,216 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) } - /* leftof - - V 1: - CRT2: x = 0 - y = 0 - w = (maxCRT2 X) - h = (virtual Y) - CRT1: x = (virtual X) - (maxCRT1 X) - y = 0 - w = (maxCRT1 X) - h = (virtual Y) - - V 2: - CRT2: x = 0 - y = 0 - w = max CRT2 mode X - h = virtual Y size - CRT1: x = (max) CRT2 mode X von dem Metamode, wo CRT1 mode maximal breit ist - y = 0 - w = max CRT1 mode X - h = virtual Y size - - V 3: (current) - CRT1: x = (maxCRT2 X von dem MMode, wo maxCRT1 X) - y = 0 - w = (virtual X) - x - h = (virtual Y) - CRT2: x = 0 - y = 0 - w = (virtual X) - (maxCRT1 X von dem MMode, wo maxCRT2 X) - h = (virtual Y) + if((usenonrect) && (info->CRT2Position != radeonClone) && info->maxCRT1_X1) { +#if 0 + switch(info->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if((info->maxCRT1_Y1 != realvirtY) && (info->maxCRT2_Y1 != realvirtY)) { + usenonrect = FALSE; + } + break; + case radeonAbove: + case radeonBelow: + if((info->maxCRT1_X1 != realvirtX) && (info->maxCRT2_X1 != realvirtX)) { + usenonrect = FALSE; + } + break; + case radeonClone: + break; + } +#endif + if(infochanged && !usenonrect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Virtual screen size does not match maximum display modes...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + + } + } else if(infochanged && usenonrect) { + usenonrect = FALSE; + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Only clone modes available for this virtual screen size...\n"); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, rectxine); + } + + if(info->maxCRT1_X1) { /* Means we have at least one non-clone mode */ + switch(info->CRT2Position) { + case radeonLeftOf: + x1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); + if(x1 < 0) x1 = 0; + y1 = info->CRT1YOffs; + w1 = pScrn1->virtualX - x1; + h1 = realvirtY; + if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { + h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; + info->NonRectDead.x0 = x1; + info->NonRectDead.x1 = x1 + w1 - 1; + info->NonRectDead.y0 = y1 + h1; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + x2 = 0; + y2 = info->CRT2YOffs; + w2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); + if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; + h2 = realvirtY; + if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { + h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; + info->NonRectDead.x0 = x2; + info->NonRectDead.x1 = x2 + w2 - 1; + info->NonRectDead.y0 = y2 + h2; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonRightOf: + x1 = 0; + y1 = info->CRT1YOffs; + w1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); + if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; + h1 = realvirtY; + if((usenonrect) && (info->maxCRT1_Y1 != realvirtY)) { + h1 = info->MBXNR1YMAX = info->maxCRT1_Y1; + info->NonRectDead.x0 = x1; + info->NonRectDead.x1 = x1 + w1 - 1; + info->NonRectDead.y0 = y1 + h1; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + x2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); + if(x2 < 0) x2 = 0; + y2 = info->CRT2YOffs; + w2 = pScrn1->virtualX - x2; + h2 = realvirtY; + if((usenonrect) && (info->maxCRT2_Y2 != realvirtY)) { + h2 = info->MBXNR2YMAX = info->maxCRT2_Y2; + info->NonRectDead.x0 = x2; + info->NonRectDead.x1 = x2 + w2 - 1; + info->NonRectDead.y0 = y2 + h2; + info->NonRectDead.y1 = pScrn1->virtualY - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonAbove: + x1 = info->CRT1XOffs; + y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); + if(y1 < 0) y1 = 0; + w1 = realvirtX; + h1 = pScrn1->virtualY - y1; + if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { + w1 = info->MBXNR1XMAX = info->maxCRT1_X1; + info->NonRectDead.x0 = x1 + w1; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = y1; + info->NonRectDead.y1 = y1 + h1 - 1; + info->HaveNonRect = TRUE; + } + x2 = info->CRT2XOffs; + y2 = 0; + w2 = realvirtX; + h2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); + if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; + if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { + w2 = info->MBXNR2XMAX = info->maxCRT2_X2; + info->NonRectDead.x0 = x2 + w2; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = y2; + info->NonRectDead.y1 = y2 + h2 - 1; + info->HaveNonRect = TRUE; + } + break; + case radeonBelow: + x1 = info->CRT1XOffs; + y1 = 0; + w1 = realvirtX; + h1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); + if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; + if((usenonrect) && (info->maxCRT1_X1 != realvirtX)) { + w1 = info->MBXNR1XMAX = info->maxCRT1_X1; + info->NonRectDead.x0 = x1 + w1; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = y1; + info->NonRectDead.y1 = y1 + h1 - 1; + info->HaveNonRect = TRUE; + } + x2 = info->CRT2XOffs; + y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); + if(y2 < 0) y2 = 0; + w2 = realvirtX; + h2 = pScrn1->virtualY - y2; + if((usenonrect) && (info->maxCRT2_X2 != realvirtX)) { + w2 = info->MBXNR2XMAX = info->maxCRT2_X2; + info->NonRectDead.x0 = x2 + w2; + info->NonRectDead.x1 = pScrn1->virtualX - 1; + info->NonRectDead.y0 = y2; + info->NonRectDead.y1 = y2 + h2 - 1; + info->HaveNonRect = TRUE; + } + default: + break; + } + + switch(info->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if(info->CRT1YOffs) { + info->OffDead1.x0 = x1; + info->OffDead1.x1 = x1 + w1 - 1; + info->OffDead1.y0 = 0; + info->OffDead1.y1 = y1 - 1; + info->OffDead2.x0 = x2; + info->OffDead2.x1 = x2 + w2 - 1; + info->OffDead2.y0 = y2 + h2; + info->OffDead2.y1 = pScrn1->virtualY - 1; + info->HaveOffsRegions = TRUE; + } else if(info->CRT2YOffs) { + info->OffDead1.x0 = x2; + info->OffDead1.x1 = x2 + w2 - 1; + info->OffDead1.y0 = 0; + info->OffDead1.y1 = y2 - 1; + info->OffDead2.x0 = x1; + info->OffDead2.x1 = x1 + w1 - 1; + info->OffDead2.y0 = y1 + h1; + info->OffDead2.y1 = pScrn1->virtualY - 1; + info->HaveOffsRegions = TRUE; + } + break; + case radeonAbove: + case radeonBelow: + if(info->CRT1XOffs) { + info->OffDead1.x0 = x2 + w2; + info->OffDead1.x1 = pScrn1->virtualX - 1; + info->OffDead1.y0 = y2; + info->OffDead1.y1 = y2 + h2 - 1; + info->OffDead2.x0 = 0; + info->OffDead2.x1 = x1 - 1; + info->OffDead2.y0 = y1; + info->OffDead2.y1 = y1 + h1 - 1; + info->HaveOffsRegions = TRUE; + } else if(info->CRT2XOffs) { + info->OffDead1.x0 = x1 + w1; + info->OffDead1.x1 = pScrn1->virtualX - 1; + info->OffDead1.y0 = y1; + info->OffDead1.y1 = y1 + h1 - 1; + info->OffDead2.x0 = 0; + info->OffDead2.x1 = x2 - 1; + info->OffDead2.y0 = y2; + info->OffDead2.y1 = y2 + h2 - 1; + info->HaveOffsRegions = TRUE; + } + default: + break; + } + + } else { /* Only clone-modes left */ + + x1 = x2 = 0; + y1 = y2 = 0; + w1 = w2 = max(info->maxClone_X1, info->maxClone_X2); + h1 = h2 = max(info->maxClone_Y1, info->maxClone_Y2); - */ - switch(info->CRT2Position) { - case radeonLeftOf: /* V 1 */ - x1 = min(info->maxCRT1_X2, pScrn1->virtualX - info->maxCRT1_X1); /* pScrn1->virtualX - pSiS->maxCRT1_X1; -*/ - if(x1 < 0) x1 = 0; - y1 = 0; /* 0; */ - w1 = pScrn1->virtualX - x1; /* pSiS->maxCRT1_X1; */ - h1 = pScrn1->virtualY; /* pScrn1->virtualY; */ - x2 = 0; /* 0; */ - y2 = 0; /* 0; */ - w2 = max(info->maxCRT2_X2, pScrn1->virtualX - info->maxCRT2_X1); /* pSiS->maxCRT2_X2; */ - if(w2 > pScrn1->virtualX) w2 = pScrn1->virtualX; - h2 = pScrn1->virtualY; /* pScrn1->virtualY; */ - break; - case radeonRightOf: - x1 = 0; /* 0; */ - y1 = 0; /* 0; */ - w1 = max(info->maxCRT1_X1, pScrn1->virtualX - info->maxCRT1_X2); /* pSiS->maxCRT1_X1; */ - if(w1 > pScrn1->virtualX) w1 = pScrn1->virtualX; - h1 = pScrn1->virtualY; /* pScrn1->virtualY; */ - x2 = min(info->maxCRT2_X1, pScrn1->virtualX - info->maxCRT2_X2); /* pScrn1->virtualX - pSiS->maxCRT2_X2; -*/ - if(x2 < 0) x2 = 0; - y2 = 0; /* 0; */ - w2 = pScrn1->virtualX - x2; /* pSiS->maxCRT2_X2; */ - h2 = pScrn1->virtualY; /* pScrn1->virtualY; */ - break; - case radeonAbove: - x1 = 0; /* 0; */ - y1 = min(info->maxCRT1_Y2, pScrn1->virtualY - info->maxCRT1_Y1); /* pScrn1->virtualY - pSiS->maxCRT1_Y1; -*/ - if(y1 < 0) y1 = 0; - w1 = pScrn1->virtualX; /* pScrn1->virtualX; */ - h1 = pScrn1->virtualY - y1; /* pSiS->maxCRT1_Y1; */ - x2 = 0; /* 0; */ - y2 = 0; /* 0; */ - w2 = pScrn1->virtualX; /* pScrn1->virtualX; */ - h2 = max(info->maxCRT2_Y2, pScrn1->virtualY - info->maxCRT2_Y1); /* pSiS->maxCRT2_Y2; */ - if(h2 > pScrn1->virtualY) h2 = pScrn1->virtualY; - break; - case radeonBelow: - x1 = 0; /* 0; */ - y1 = 0; /* 0; */ - w1 = pScrn1->virtualX; /* pScrn1->virtualX; */ - h1 = max(info->maxCRT1_Y1, pScrn1->virtualY - info->maxCRT1_Y2); /* pSiS->maxCRT1_Y1; */ - if(h1 > pScrn1->virtualY) h1 = pScrn1->virtualY; - x2 = 0; /* 0; */ - y2 = min(info->maxCRT2_Y1, pScrn1->virtualY - info->maxCRT2_Y2); /* pScrn1->virtualY - pSiS->maxCRT2_Y2; -*/ - if(y2 < 0) y2 = 0; - w2 = pScrn1->virtualX; /* pScrn1->virtualX; */ - h2 = pScrn1->virtualY - y2; /* pSiS->maxCRT2_Y2; */ - break; - default: - xf86DrvMsg(pScrn1->scrnIndex, X_ERROR, - "Internal error: UpdateXineramaInfo(): unsupported CRT2Position (%d)\n", - info->CRT2Position); } + RADEONXineramadataPtr[crt1scrnnum].x = x1; RADEONXineramadataPtr[crt1scrnnum].y = y1; RADEONXineramadataPtr[crt1scrnnum].width = w1; @@ -700,15 +926,34 @@ RADEONUpdateXineramaScreenInfo(ScrnInfoPtr pScrn1) if(infochanged) { xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", - crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); + "Pseudo-Xinerama: CRT1 (Screen %d) (%d,%d)-(%d,%d)\n", + crt1scrnnum, x1, y1, w1+x1-1, h1+y1-1); xf86DrvMsg(pScrn1->scrnIndex, X_INFO, - "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", - crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); + "Pseudo-Xinerama: CRT2 (Screen %d) (%d,%d)-(%d,%d)\n", + crt2scrnnum, x2, y2, w2+x2-1, h2+y2-1); + if(info->HaveNonRect) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible area (%d,%d)-(%d,%d)\n", + info->NonRectDead.x0, info->NonRectDead.y0, + info->NonRectDead.x1, info->NonRectDead.y1); + } + if(info->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + info->OffDead1.x0, info->OffDead1.y0, + info->OffDead1.x1, info->OffDead1.y1); + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Pseudo-Xinerama: Inaccessible offset area (%d,%d)-(%d,%d)\n", + info->OffDead2.x0, info->OffDead2.y0, + info->OffDead2.x1, info->OffDead2.y1); + } + if(info->HaveNonRect || info->HaveOffsRegions) { + xf86DrvMsg(pScrn1->scrnIndex, X_INFO, + "Mouse restriction for inaccessible areas is %s\n", + info->MouseRestrictions ? "enabled" : "disabled"); + } } - } - /* Proc */ int @@ -997,6 +1242,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) if(!info->MergedFB) { RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; return; } @@ -1005,6 +1251,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xinerama active, not initializing Radeon Pseudo-Xinerama\n"); RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; return; } #endif @@ -1012,6 +1259,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) if(RADEONnoPanoramiXExtension) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Radeon Pseudo-Xinerama disabled\n"); + info->MouseRestrictions = FALSE; return; } @@ -1019,6 +1267,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Running MergedFB in Clone mode, Radeon Pseudo-Xinerama disabled\n"); RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; return; } @@ -1026,6 +1275,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Only Clone modes defined, Radeon Pseudo-Xinerama disabled\n"); RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; return; } @@ -1054,6 +1304,7 @@ RADEONXineramaExtensionInit(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to initialize Radeon Pseudo-Xinerama extension\n"); RADEONnoPanoramiXExtension = TRUE; + info->MouseRestrictions = FALSE; return; } @@ -1084,14 +1335,89 @@ RADEONMergePointerMoved(int scrnIndex, int x, int y) ScrnInfoPtr pScrn2 = info->CRT2pScrn; region out, in1, in2, f2, f1; int deltax, deltay; + int temp1, temp2; + int old1x0, old1y0, old2x0, old2y0; + int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + int sigstate; + Bool doit = FALSE, HaveNonRect = FALSE, HaveOffsRegions = FALSE; + RADEONScrn2Rel srel = ((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position; + + if(info->DGAactive) { + return; + /* DGA: There is no cursor and no panning while DGA is active. */ + /* If it were, we would need to do: */ + /* HVirt = info->CurrentLayout.displayWidth; + VVirt = info->CurrentLayout.displayHeight; + BOUND(x, info->CurrentLayout.DGAViewportX, HVirt); + BOUND(y, info->CurrentLayout.DGAViewportY, VVirt); */ + } else { + CRT1XOffs = info->CRT1XOffs; + CRT1YOffs = info->CRT1YOffs; + CRT2XOffs = info->CRT2XOffs; + CRT2YOffs = info->CRT2YOffs; + HaveNonRect = info->HaveNonRect; + HaveOffsRegions = info->HaveOffsRegions; + } + + /* Check if the pointer is inside our dead areas */ + if((info->MouseRestrictions) && (srel != radeonClone) && !RADEONnoPanoramiXExtension) { + if(HaveNonRect) { + if(InRegion(x, y, info->NonRectDead)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->NonRectDead.y0 - 1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->NonRectDead.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(HaveOffsRegions) { + if(InRegion(x, y, info->OffDead1)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->OffDead1.y1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->OffDead1.x1; + doit = TRUE; + default: break; + } + } else if(InRegion(x, y, info->OffDead2)) { + switch(srel) { + case radeonLeftOf: + case radeonRightOf: y = info->OffDead2.y0 - 1; + doit = TRUE; + break; + case radeonAbove: + case radeonBelow: x = info->OffDead2.x0 - 1; + doit = TRUE; + default: break; + } + } + } + if(doit) { + UpdateCurrentTime(); + sigstate = xf86BlockSIGIO(); + miPointerAbsoluteCursor(x, y, currentTime.milliseconds); + xf86UnblockSIGIO(sigstate); + return; + } + } - f1.x0 = info->CRT1frameX0; + f1.x0 = old1x0 = info->CRT1frameX0; f1.x1 = info->CRT1frameX1; - f1.y0 = info->CRT1frameY0; + f1.y0 = old1y0 = info->CRT1frameY0; f1.y1 = info->CRT1frameY1; - f2.x0 = pScrn2->frameX0; + f2.x0 = old2x0 = pScrn2->frameX0; f2.x1 = pScrn2->frameX1; - f2.y0 = pScrn2->frameY0; + f2.y0 = old2y0 = pScrn2->frameY0; f2.y1 = pScrn2->frameY1; /* Define the outer region. Crossing this causes all frames to move */ @@ -1106,7 +1432,7 @@ RADEONMergePointerMoved(int scrnIndex, int x, int y) */ in1 = out; in2 = out; - switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { + switch(srel) { case radeonLeftOf: in1.x0 = f1.x0; in2.x1 = f2.x1; @@ -1185,7 +1511,7 @@ RADEONMergePointerMoved(int scrnIndex, int x, int y) f2.y1 += deltay; } - switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { + switch(srel) { case radeonLeftOf: if(x >= f1.x0) { REBOUND(f1.y0, f1.y1, y); } if(x <= f2.x1) { REBOUND(f2.y0, f2.y1, y); } @@ -1214,12 +1540,65 @@ RADEONMergePointerMoved(int scrnIndex, int x, int y) pScrn2->frameX0 = f2.x0; pScrn2->frameY0 = f2.y0; + switch(((RADEONMergedDisplayModePtr)info->CurrentLayout.mode->Private)->CRT2Position) { + case radeonLeftOf: + case radeonRightOf: + if(info->CRT1YOffs || info->CRT2YOffs || HaveNonRect) { + if(info->CRT1frameY0 != old1y0) { + if(info->CRT1frameY0 < info->CRT1YOffs) + info->CRT1frameY0 = info->CRT1YOffs; + temp1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay; + /*temp2 = pScrn1->virtualY - info->CRT2YOffs;*/ + temp2 = min((VVirt - CRT2YOffs), (CRT1YOffs + info->MBXNR1YMAX)); + if(temp1 > temp2) + info->CRT1frameY0 -= (temp1 - temp2); + } + if(pScrn2->frameY0 != old2y0) { + if(pScrn2->frameY0 < info->CRT2YOffs) + pScrn2->frameY0 = info->CRT2YOffs; + temp1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay; + /*temp2 = pScrn1->virtualY - info->CRT1YOffs;*/ + temp2 = min((VVirt - CRT1YOffs), (CRT2YOffs + info->MBXNR2YMAX)); + if(temp1 > temp2) + pScrn2->frameY0 -= (temp1 - temp2); + } + } + break; + case radeonBelow: + case radeonAbove: + if(info->CRT1XOffs || info->CRT2XOffs || HaveNonRect) { + if(info->CRT1frameX0 != old1x0) { + if(info->CRT1frameX0 < info->CRT1XOffs) + info->CRT1frameX0 = info->CRT1XOffs; + temp1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay; + /*temp2 = pScrn1->virtualX - info->CRT2XOffs;*/ + temp2 = min((HVirt - CRT2XOffs), (CRT1XOffs + info->MBXNR1XMAX)); + if(temp1 > temp2) + info->CRT1frameX0 -= (temp1 - temp2); + } + if(pScrn2->frameX0 != old2x0) { + if(pScrn2->frameX0 < info->CRT2XOffs) + pScrn2->frameX0 = info->CRT2XOffs; + temp1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay; + /*temp2 = pScrn1->virtualX - info->CRT1XOffs;*/ + temp2 = min((HVirt - CRT1XOffs), (CRT2XOffs + info->MBXNR2XMAX)); + if(temp1 > temp2) + pScrn2->frameX0 -= (temp1 - temp2); + } + } + break; + case radeonClone: + break; + } + info->CRT1frameX1 = info->CRT1frameX0 + CDMPTR->CRT1->HDisplay - 1; info->CRT1frameY1 = info->CRT1frameY0 + CDMPTR->CRT1->VDisplay - 1; pScrn2->frameX1 = pScrn2->frameX0 + CDMPTR->CRT2->HDisplay - 1; pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; +#if 0 pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; +#endif RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); @@ -1236,40 +1615,81 @@ RADEONAdjustFrameMergedHelper(int scrnIndex, int x, int y, int flags) int HTotal = info->CurrentLayout.mode->HDisplay; int VMax = VTotal; int HMax = HTotal; + int HVirt = pScrn1->virtualX; + int VVirt = pScrn1->virtualY; + int x1 = x, x2 = x; + int y1 = y, y2 = y; + int CRT1XOffs = 0, CRT1YOffs = 0, CRT2XOffs = 0, CRT2YOffs = 0; + int MBXNR1XMAX = 65536, MBXNR1YMAX = 65536, MBXNR2XMAX = 65536, MBXNR2YMAX = 65536; + + if(info->DGAactive) { + HVirt = info->CurrentLayout.displayWidth; + VVirt = info->CurrentLayout.displayHeight; + } else { + CRT1XOffs = info->CRT1XOffs; + CRT1YOffs = info->CRT1YOffs; + CRT2XOffs = info->CRT2XOffs; + CRT2YOffs = info->CRT2YOffs; + MBXNR1XMAX = info->MBXNR1XMAX; + MBXNR1YMAX = info->MBXNR1YMAX; + MBXNR2XMAX = info->MBXNR2XMAX; + MBXNR2YMAX = info->MBXNR2YMAX; + } + BOUND(x, 0, pScrn1->virtualX - HTotal); BOUND(y, 0, pScrn1->virtualY - VTotal); + if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { +#if 0 + BOUND(x1, info->CRT1XOffs, pScrn1->virtualX - HTotal - info->CRT2XOffs); + BOUND(y1, info->CRT1YOffs, pScrn1->virtualY - VTotal - info->CRT2YOffs); + BOUND(x2, info->CRT2XOffs, pScrn1->virtualX - HTotal - info->CRT1XOffs); + BOUND(y2, info->CRT2YOffs, pScrn1->virtualY - VTotal - info->CRT1YOffs); +#endif + BOUND(x1, CRT1XOffs, min(HVirt, MBXNR1XMAX + CRT1XOffs) - min(HTotal, MBXNR1XMAX) - CRT2XOffs); + BOUND(y1, CRT1YOffs, min(VVirt, MBXNR1YMAX + CRT1YOffs) - min(VTotal, MBXNR1YMAX) - CRT2YOffs); + BOUND(x2, CRT2XOffs, min(HVirt, MBXNR2XMAX + CRT2XOffs) - min(HTotal, MBXNR2XMAX) - CRT1XOffs); + BOUND(y2, CRT2YOffs, min(VVirt, MBXNR2YMAX + CRT2YOffs) - min(VTotal, MBXNR2YMAX) - CRT1YOffs); + } switch(SDMPTR(pScrn1)->CRT2Position) { case radeonLeftOf: - pScrn2->frameX0 = x; - BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); - info->CRT1frameX0 = x + CDMPTR->CRT2->HDisplay; - BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + pScrn2->frameX0 = x2; + /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ + BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); + info->CRT1frameX0 = x1 + CDMPTR->CRT2->HDisplay; + /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ + BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); break; case radeonRightOf: - info->CRT1frameX0 = x; - BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); - pScrn2->frameX0 = x + CDMPTR->CRT1->HDisplay; - BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + info->CRT1frameX0 = x1; + /*BOUND(info->CRT1frameY0, y1, y1 + VMax - CDMPTR->CRT1->VDisplay);*/ + BOUND(info->CRT1frameY0, y1, y1 + min(VMax, MBXNR1YMAX) - CDMPTR->CRT1->VDisplay); + pScrn2->frameX0 = x2 + CDMPTR->CRT1->HDisplay; + /*BOUND(pScrn2->frameY0, y2, y2 + VMax - CDMPTR->CRT2->VDisplay);*/ + BOUND(pScrn2->frameY0, y2, y2 + min(VMax, MBXNR2YMAX) - CDMPTR->CRT2->VDisplay); break; case radeonAbove: - BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y; - BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y + CDMPTR->CRT2->VDisplay; + /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ + BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = y2; + /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ + BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = y1 + CDMPTR->CRT2->VDisplay; break; case radeonBelow: - BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); - info->CRT1frameY0 = y; - BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); - pScrn2->frameY0 = y + CDMPTR->CRT1->VDisplay; + /*BOUND(info->CRT1frameX0, x1, x1 + HMax - CDMPTR->CRT1->HDisplay);*/ + BOUND(info->CRT1frameX0, x1, x1 + min(HMax, MBXNR1XMAX) - CDMPTR->CRT1->HDisplay); + info->CRT1frameY0 = y1; + /*BOUND(pScrn2->frameX0, x2, x2 + HMax - CDMPTR->CRT2->HDisplay);*/ + BOUND(pScrn2->frameX0, x2, x2 + min(HMax, MBXNR2XMAX) - CDMPTR->CRT2->HDisplay); + pScrn2->frameY0 = y2 + CDMPTR->CRT1->VDisplay; break; case radeonClone: - BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); - BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); - BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); - BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); + BOUND(info->CRT1frameX0, x, x + HMax - CDMPTR->CRT1->HDisplay); + BOUND(info->CRT1frameY0, y, y + VMax - CDMPTR->CRT1->VDisplay); + BOUND(pScrn2->frameX0, x, x + HMax - CDMPTR->CRT2->HDisplay); + BOUND(pScrn2->frameY0, y, y + VMax - CDMPTR->CRT2->VDisplay); break; } @@ -1287,6 +1707,12 @@ RADEONAdjustFrameMergedHelper(int scrnIndex, int x, int y, int flags) pScrn2->frameY1 = pScrn2->frameY0 + CDMPTR->CRT2->VDisplay - 1; pScrn1->frameX1 = pScrn1->frameX0 + info->CurrentLayout.mode->HDisplay - 1; pScrn1->frameY1 = pScrn1->frameY0 + info->CurrentLayout.mode->VDisplay - 1; + + if(SDMPTR(pScrn1)->CRT2Position != radeonClone) { + pScrn1->frameX1 += CRT1XOffs + CRT2XOffs; + pScrn1->frameY1 += CRT1YOffs + CRT2YOffs; + } + /* RADEONDoAdjustFrame(pScrn1, info->CRT1frameX0, info->CRT1frameY0, FALSE); RADEONDoAdjustFrame(pScrn1, pScrn2->frameX0, pScrn2->frameY0, TRUE); diff --git a/src/radeon_mergedfb.h b/src/radeon_mergedfb.h index 3ad65a6..a2c792c 100644 --- a/src/radeon_mergedfb.h +++ b/src/radeon_mergedfb.h @@ -82,10 +82,6 @@ typedef struct _MergedDisplayModeRec { RADEONScrn2Rel CRT2Position; } RADEONMergedDisplayModeRec, *RADEONMergedDisplayModePtr; -typedef struct _region { - int x0,x1,y0,y1; -} region; - typedef struct _RADEONXineramaData { int x; int y; |