summaryrefslogtreecommitdiff
path: root/src/smi_driver.c
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@gmail.com>2008-08-16 13:00:31 +0200
committerPaulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>2008-08-16 19:16:28 -0300
commit209097ba5b44a0ce0da7f1ea52150dcace2b5244 (patch)
treecf75b4a605fb5448bd6cc9d4e70ad0ccaab7ec74 /src/smi_driver.c
parent45c6aedd6fe4e4d6abe58d1bb39ec01049404f09 (diff)
RandR rotation implemented.
* I added the configuration file option "RandRRotation". * I replaced pSmi->ShadowPitch with pSmi->screenStride, it seems it makes more sense because the lower word of ShadowPitch may change independently. * I moved the SMI_DEDataFormat to smi_accel.c because it seems it is a piece of code repeated many times in the driver. * At some places, it is assumed the framebuffer is at FBOffset: when using a shadow framebuffer, FBOffset is the location of the on-screen framebuffer (0 should be used). This made e.g. EXA completly useless with ShadowFB enabled (it crashed). * In the FBManager initialization, I have replaced xf86InitFBManager with xf86InitFBManagerRegion to reserve some additional space as screen fb: it's unlikely to be the case, but a less efficient alignment in the rotated mode could make the rotated mode need more memory than the unrotated one. This is not a problem with EXA as the offscreen memory parameters can be easily modified when doing the rotation. * In SMI_RefreshArea it's assumed that some DE registers are already in some state, this is specially not true when using EXA. * SMI_ValidMode rejects a rotated mode with different dimensions than the panel. This seems to work now. Signed-off-by: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br>
Diffstat (limited to 'src/smi_driver.c')
-rw-r--r--src/smi_driver.c191
1 files changed, 140 insertions, 51 deletions
diff --git a/src/smi_driver.c b/src/smi_driver.c
index 6e4de86..ea9c5da 100644
--- a/src/smi_driver.c
+++ b/src/smi_driver.c
@@ -84,6 +84,7 @@ static unsigned int SMI_ddc1Read(ScrnInfoPtr pScrn);
static void SMI_FreeScreen(int ScrnIndex, int flags);
static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
static void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
+static Bool SMI_DriverFunc(ScrnInfoPtr pScrn , xorgDriverFuncOp op,pointer ptr);
#define SILICONMOTION_NAME "Silicon Motion"
@@ -164,6 +165,7 @@ typedef enum
OPTION_ZOOMONLCD,
OPTION_DUALHEAD,
OPTION_ACCELMETHOD,
+ OPTION_RANDRROTATION,
NUMBER_OF_OPTIONS
} SMIOpts;
@@ -190,6 +192,7 @@ static const OptionInfoRec SMIOptions[] =
{ OPTION_ZOOMONLCD, "ZoomOnLCD", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_RANDRROTATION, "RandRRotation", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -696,6 +699,11 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
pSmi->MCLK = 0;
}
+ if(!pSmi->randrRotation && xf86GetOptValBool(pSmi->Options, OPTION_RANDRROTATION, &pSmi->randrRotation)){
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "RandRRotation %s.\n",
+ pSmi->randrRotation ? "enabled" : "disabled");
+ }
+
from = X_DEFAULT;
pSmi->hwcursor = TRUE;
if (xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->hwcursor)) {
@@ -705,14 +713,24 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags)
pSmi->hwcursor = FALSE;
from = X_CONFIG;
}
- xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n",
- pSmi->hwcursor ? "Hardware" : "Software");
+ if(pSmi->hwcursor && pSmi->randrRotation){
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "RandRRotation enabled: Disabling hardware cursor.\n");
+ pSmi->hwcursor = FALSE;
+ }else{
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s Cursor\n",
+ pSmi->hwcursor ? "Hardware" : "Software");
+ }
if (xf86GetOptValBool(pSmi->Options, OPTION_SHADOW_FB, &pSmi->shadowFB)) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
pSmi->shadowFB ? "enabled" : "disabled");
}
+ if(!pSmi->shadowFB && pSmi->randrRotation){
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RandRRotation enabled: Enabling ShadowFB.\n");
+ pSmi->shadowFB = TRUE;
+ }
+
#if 1 /* PDR#932 */
if ((pScrn->depth == 8) || (pScrn->depth == 16))
#endif /* PDR#932 */
@@ -1230,8 +1248,8 @@ SMI_EnterVT(int scrnIndex, int flags)
box.x1 = 0;
box.y1 = 0;
- box.x2 = pScrn->virtualY;
- box.y2 = pScrn->virtualX;
+ box.x2 = pSmi->width;
+ box.y2 = pSmi->height;
if (pSmi->Chipset == SMI_COUGAR3DR) {
SMI_RefreshArea730(pScrn, 1, &box);
} else {
@@ -2051,6 +2069,12 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
/* Zero the frame buffer, #258 */
memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
+
+ /* Callback for RandR rotation */
+ pScrn->DriverFunc = SMI_DriverFunc;
+ if(pSmi->randrRotation)
+ pSmi->rotate=0;
+
/* Initialize the first mode */
if (!SMI_ModeInit(pScrn, pScrn->currentMode)) {
LEAVE_PROC("SMI_ScreenInit");
@@ -2111,8 +2135,9 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!pSmi->useEXA) {
int numLines, maxLines;
BoxRec AvailFBArea;
-
- maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp);
+ RegionRec AvailFBRegion;
+
+ maxLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
if (pSmi->rotate) {
numLines = maxLines;
} else {
@@ -2129,14 +2154,20 @@ SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
}
AvailFBArea.x1 = 0;
- AvailFBArea.y1 = 0;
- AvailFBArea.x2 = pSmi->width;
+ if(pSmi->randrRotation) /* The rotated mode could need more memory */
+ AvailFBArea.y1= max(((pScrn->virtualX * pSmi->Bpp + 15) & ~15)*pScrn->virtualY,
+ ((pScrn->virtualY * pSmi->Bpp + 15) & ~15)*pScrn->virtualX)/(pScrn->virtualX*pSmi->Bpp);
+ else
+ AvailFBArea.y1 = pScrn->virtualY;
+ AvailFBArea.x2 = pScrn->virtualX;
AvailFBArea.y2 = numLines;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"FrameBuffer Box: %d,%d - %d,%d\n",
AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
AvailFBArea.y2);
- xf86InitFBManager(pScreen, &AvailFBArea);
+ REGION_INIT(pScreen,&AvailFBRegion,&AvailFBArea,1);
+ xf86InitFBManagerRegion(pScreen, &AvailFBRegion);
+ REGION_UNINIT(pScreen,&AvailFBRegion);
}
/* end CZ */
@@ -2239,7 +2270,7 @@ SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
SMIPtr pSmi = SMIPTR(pScrn);
- int width, height, displayWidth;
+ int width, height;
int bytesPerPixel = pScrn->bitsPerPixel / 8;
int xDpi, yDpi;
int ret;
@@ -2251,26 +2282,21 @@ SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
height = pScrn->virtualX;
xDpi = pScrn->yDpi;
yDpi = pScrn->xDpi;
- displayWidth = ((width * bytesPerPixel + 15) & ~15) / bytesPerPixel;
} else {
width = pScrn->virtualX;
height = pScrn->virtualY;
xDpi = pScrn->xDpi;
yDpi = pScrn->yDpi;
- displayWidth = pScrn->displayWidth;
}
+ pScrn->displayWidth = ((width * bytesPerPixel + 15) & ~15) / bytesPerPixel;
if (pSmi->shadowFB) {
pSmi->ShadowWidth = width;
pSmi->ShadowHeight = height;
- pSmi->ShadowWidthBytes = (width * bytesPerPixel + 15) & ~15;
- if (bytesPerPixel == 3) {
- pSmi->ShadowPitch = ((height * 3) << 16)
- | pSmi->ShadowWidthBytes;
- } else {
- pSmi->ShadowPitch = (height << 16)
- | (pSmi->ShadowWidthBytes / bytesPerPixel);
- }
+ pSmi->ShadowWidthBytes = pScrn->displayWidth*bytesPerPixel;
+ pSmi->screenStride = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15)/ pSmi->Bpp;
+ if(pScrn->bitsPerPixel==24)
+ pSmi->screenStride *= 3;
pSmi->saveBufferSize = pSmi->ShadowWidthBytes * pSmi->ShadowHeight;
pSmi->FBReserved -= pSmi->saveBufferSize;
@@ -2282,10 +2308,9 @@ SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Shadow: width=%d height=%d "
- "offset=0x%08lX pitch=0x%08X\n",
+ "offset=0x%08lX\n",
pSmi->ShadowWidth, pSmi->ShadowHeight,
- (unsigned long)pSmi->FBOffset,
- pSmi->ShadowPitch);
+ (unsigned long)pSmi->FBOffset);
} else {
pSmi->FBOffset = 0;
pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
@@ -2297,14 +2322,14 @@ SMI_InternalScreenInit(int scrnIndex, ScreenPtr pScreen)
*/
DEBUG((VERBLEV, "\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
- pSmi->FBBase, width, height, displayWidth));
+ pSmi->FBBase, width, height, pScrn->displayWidth));
switch (pScrn->bitsPerPixel) {
case 8:
case 16:
case 24:
case 32:
ret = fbScreenInit(pScreen, pSmi->FBBase, width, height, xDpi,
- yDpi, displayWidth, pScrn->bitsPerPixel);
+ yDpi, pScrn->displayWidth, pScrn->bitsPerPixel);
break;
default:
xf86DrvMsg(scrnIndex, X_ERROR, "Internal error: invalid bpp (%d) "
@@ -2368,13 +2393,13 @@ SMI_ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
}
#if 1 /* PDR#944 */
- if (pSmi->rotate) {
- if ((mode->HDisplay != pSmi->lcdWidth) ||
- (mode->VDisplay != pSmi->lcdHeight)) {
- LEAVE_PROC("SMI_ValidMode");
- return MODE_PANEL;
- }
- }
+/* if (pSmi->rotate) { */
+/* if ((mode->HDisplay != pSmi->lcdWidth) || */
+/* (mode->VDisplay != pSmi->lcdHeight)) { */
+/* LEAVE_PROC("SMI_ValidMode"); */
+/* return MODE_PANEL; */
+/* } */
+/* } */
#endif
LEAVE_PROC("SMI_ValidMode");
@@ -2393,23 +2418,11 @@ SMI_DPRInit(ScrnInfoPtr pScrn)
SMIRegPtr new = &pSmi->ModeReg;
/* Set DPR registers */
- pSmi->Stride = (pSmi->width * pSmi->Bpp + 15) & ~15;
- switch (pScrn->bitsPerPixel) {
- case 8:
- DEDataFormat = 0x00000000;
- break;
- case 16:
- pSmi->Stride >>= 1;
- DEDataFormat = 0x00100000;
- break;
- case 24:
- DEDataFormat = 0x00300000;
- break;
- case 32:
- pSmi->Stride >>= 2;
- DEDataFormat = 0x00200000;
- break;
- }
+ pSmi->Stride = ((pSmi->width * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
+ if(pScrn->bitsPerPixel==24)
+ pSmi->Stride *= 3;
+
+ DEDataFormat=SMI_DEDataFormat(pScrn->bitsPerPixel);
for (i = 0; i < sizeof(xyAddress) / sizeof(xyAddress[0]); i++) {
if (pSmi->rotate) {
@@ -2433,8 +2446,13 @@ SMI_DPRInit(ScrnInfoPtr pScrn)
new->DPR2C = 0;
new->DPR30 = 0;
new->DPR3C = (pSmi->Stride << 16) | pSmi->Stride;
- new->DPR40 = pSmi->FBOffset >> 3;
- new->DPR44 = pSmi->FBOffset >> 3;
+ if(pSmi->shadowFB){
+ new->DPR40 = 0;
+ new->DPR44 = 0; /* The shadow framebuffer is located at offset 0 */
+ }else{
+ new->DPR40 = pSmi->FBOffset >> 3;
+ new->DPR44 = pSmi->FBOffset >> 3;
+ }
}
@@ -2804,6 +2822,8 @@ SMI_ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
SMI_WriteMode(pScrn, vganew, new);
/* Adjust the viewport */
+ pScrn->frameX1=pScrn->frameX0 + pScrn->currentMode->HDisplay - 1;
+ pScrn->frameY1=pScrn->frameY0 + pScrn->currentMode->VDisplay - 1;
SMI_AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
LEAVE_PROC("SMI_ModeInit");
@@ -3361,3 +3381,72 @@ SMI_ddc1(int scrnIndex)
return success;
}
+static void SMI_SetShadowDimensions(ScrnInfoPtr pScrn,int width,int height){
+ SMIPtr pSmi = SMIPTR(pScrn);
+ pScrn->displayWidth=width;
+ pSmi->ShadowWidth = pSmi->width = width;
+ pSmi->ShadowHeight = pSmi->height= height;
+ pSmi->ShadowWidthBytes = width * pSmi->Bpp;
+ pSmi->saveBufferSize = pSmi->ShadowWidthBytes * height;
+ pSmi->Stride = ((pScrn->displayWidth * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
+ if(pScrn->bitsPerPixel==24)
+ pSmi->Stride*=3;
+ pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),width,height,-1,-1,width*pSmi->Bpp,NULL);
+ if(pSmi->EXADriverPtr){
+ pSmi->EXADriverPtr->offScreenBase = pScrn->displayWidth * pSmi->height * pSmi->Bpp;
+ }
+}
+
+static Bool
+SMI_DriverFunc(ScrnInfoPtr pScrn , xorgDriverFuncOp op,pointer ptr){
+ SMIPtr pSmi = SMIPTR(pScrn);
+
+ ENTER_PROC("SMI_DriverFunc");
+ if(op==RR_GET_INFO){
+ if(pSmi->randrRotation)
+ ((xorgRRRotation*)ptr)->RRRotations = RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_270;
+ else
+ ((xorgRRRotation*)ptr)->RRRotations = RR_Rotate_0;
+
+ }else if(op==RR_SET_CONFIG){
+ if(!pSmi->randrRotation){
+ LEAVE_PROC("SMI_DriverFunc");
+ return FALSE;
+ }
+
+ xorgRRConfig rconf= ((xorgRRRotation*)ptr)->RRConfig;
+ if(rconf.rotation==RR_Rotate_0){
+ if(pSmi->rotate!=0){
+ if(pSmi->PointerMoved != NULL){
+ pScrn->PointerMoved = pSmi->PointerMoved;
+ pSmi->PointerMoved = NULL;
+ }
+ SMI_SetShadowDimensions(pScrn,rconf.width,rconf.height);
+ }
+ pSmi->rotate=0;
+ }else if(rconf.rotation==RR_Rotate_90 || rconf.rotation==RR_Rotate_270){
+ if(pSmi->rotate==0){
+ if(pSmi->PointerMoved == NULL){
+ pSmi->PointerMoved = pScrn->PointerMoved;
+ pScrn->PointerMoved = SMI_PointerMoved;
+ }
+ SMI_SetShadowDimensions(pScrn,rconf.height,rconf.width);
+ }
+
+ if(rconf.rotation==RR_Rotate_90)
+ pSmi->rotate=SMI_ROTATE_CCW;
+ else
+ pSmi->rotate=SMI_ROTATE_CW;
+
+ }else{
+ LEAVE_PROC("SMI_DriverFunc");
+ return FALSE;
+ }
+ }else{
+ LEAVE_PROC("SMI_DriverFunc");
+ return FALSE;
+ }
+
+ LEAVE_PROC("SMI_DriverFunc");
+ return TRUE;
+}