diff options
-rw-r--r-- | src/wsfb_driver.c | 234 |
1 files changed, 199 insertions, 35 deletions
diff --git a/src/wsfb_driver.c b/src/wsfb_driver.c index 4844d3d..d97bf3f 100644 --- a/src/wsfb_driver.c +++ b/src/wsfb_driver.c @@ -114,6 +114,7 @@ static Bool WsfbScreenInit(int, ScreenPtr, int, char **); static Bool WsfbCloseScreen(int, ScreenPtr); static void *WsfbWindowLinear(ScreenPtr, CARD32, CARD32, int, CARD32 *, void *); +static void WsfbPointerMoved(int, int, int); static Bool WsfbEnterVT(int, int); static void WsfbLeaveVT(int, int); static Bool WsfbSwitchMode(int, DisplayModePtr, int); @@ -138,17 +139,23 @@ static Bool WsfbDriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, static int wsfb_open(char *); static pointer wsfb_mmap(size_t, off_t, int); +enum { WSFB_ROTATE_NONE = 0, + WSFB_ROTATE_CCW = 90, + WSFB_ROTATE_UD = 180, + WSFB_ROTATE_CW = 270 +}; + /* * This is intentionally screen-independent. It indicates the binding * choice made in the first PreInit. */ static int pix24bpp = 0; -#define WSFB_VERSION 4000 +#define WSFB_VERSION 4000 #define WSFB_NAME "wsfb" #define WSFB_DRIVER_NAME "wsfb" #define WSFB_MAJOR_VERSION 0 -#define WSFB_MINOR_VERSION 1 +#define WSFB_MINOR_VERSION 2 _X_EXPORT DriverRec WSFB = { WSFB_VERSION, @@ -170,10 +177,12 @@ static SymTabRec WsfbChipsets[] = { /* Supported options */ typedef enum { OPTION_SHADOW_FB, + OPTION_ROTATE } WsfbOpts; static const OptionInfoRec WsfbOptions[] = { { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE}, + { OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE}, { -1, NULL, OPTV_NONE, {0}, FALSE} }; @@ -184,8 +193,12 @@ static const char *fbSymbols[] = { NULL }; static const char *shadowSymbols[] = { - "shadowInit", + "shadowAdd", + "shadowSetup", + "shadowUpdatePacked", "shadowUpdatePackedWeak", + "shadowUpdateRotatePacked", + "shadowUpdateRotatePackedWeak", NULL }; @@ -242,13 +255,12 @@ typedef struct { unsigned char* fbstart; unsigned char* fbmem; size_t fbmem_len; + int rotate; Bool shadowFB; CloseScreenProcPtr CloseScreen; + void (*PointerMoved)(int, int, int); EntityInfoPtr pEnt; struct wsdisplay_cmap saved_cmap; - unsigned char saved_red[256]; - unsigned char saved_green[256]; - unsigned char saved_blue[256]; #ifdef XFreeXDGA /* DGA info */ @@ -373,7 +385,7 @@ WsfbProbe(DriverPtr drv, int flags) NULL,NULL,NULL,NULL); if (pScrn != NULL) { foundScreen = TRUE; - pScrn->driverVersion = VERSION; + pScrn->driverVersion = WSFB_VERSION; pScrn->driverName = WSFB_DRIVER_NAME; pScrn->name = WSFB_NAME; pScrn->Probe = WsfbProbe; @@ -401,7 +413,7 @@ WsfbPreInit(ScrnInfoPtr pScrn, int flags) { WsfbPtr fPtr; int default_depth, wstype; - char *dev; + char *dev, *s; char *mod = NULL; const char *reqSym = NULL; Gamma zeros = {0.0, 0.0, 0.0}; @@ -447,6 +459,35 @@ WsfbPreInit(ScrnInfoPtr pScrn, int flags) strerror(errno)); return FALSE; } + /* + * Allocate room for saving the colormap + */ + if (fPtr->info.cmsize != 0) { + fPtr->saved_cmap.red = + (unsigned char *)xalloc(fPtr->info.cmsize); + if (fPtr->saved_cmap.red == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot malloc %d bytes\n", fPtr->info.cmsize); + return FALSE; + } + fPtr->saved_cmap.green = + (unsigned char *)xalloc(fPtr->info.cmsize); + if (fPtr->saved_cmap.green == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot malloc %d bytes\n", fPtr->info.cmsize); + xfree(fPtr->saved_cmap.red); + return FALSE; + } + fPtr->saved_cmap.blue = + (unsigned char *)xalloc(fPtr->info.cmsize); + if (fPtr->saved_cmap.blue == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Cannot malloc %d bytes\n", fPtr->info.cmsize); + xfree(fPtr->saved_cmap.red); + xfree(fPtr->saved_cmap.green); + return FALSE; + } + } /* Handle depth */ default_depth = fPtr->info.depth <= 24 ? fPtr->info.depth : 24; @@ -531,9 +572,42 @@ WsfbPreInit(ScrnInfoPtr pScrn, int flags) if (xf86ReturnOptValBool(fPtr->Options, OPTION_SHADOW_FB, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Shadow FB option ignored on depth 1"); + "Shadow FB option ignored on depth < 8"); } + /* rotation */ + fPtr->rotate = WSFB_ROTATE_NONE; + if ((s = xf86GetOptValString(fPtr->Options, OPTION_ROTATE))) { + if (pScrn->depth >= 8) { + if (!xf86NameCmp(s, "CW")) { + fPtr->shadowFB = TRUE; + fPtr->rotate = WSFB_ROTATE_CW; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen clockwise\n"); + } else if (!xf86NameCmp(s, "CCW")) { + fPtr->shadowFB = TRUE; + fPtr->rotate = WSFB_ROTATE_CCW; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen counter clockwise\n"); + } else if (!xf86NameCmp(s, "UD")) { + fPtr->shadowFB = TRUE; + fPtr->rotate = WSFB_ROTATE_UD; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Rotating screen upside down\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "\"%s\" is not a valid value for Option " + "\"Rotate\"\n", s); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Valid options are \"CW\", \"CCW\"," + " or \"UD\"\n"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Option \"Rotate\" ignored on depth < 8"); + } + } + /* fake video mode struct */ mode = (DisplayModePtr)xalloc(sizeof(DisplayModeRec)); mode->prev = mode; @@ -612,14 +686,14 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; WsfbPtr fPtr = WSFBPTR(pScrn); VisualPtr visual; - int ret, flags, width, height; + int ret, flags, width, height, ncolors; int wsmode = WSDISPLAYIO_MODE_DUMBFB; size_t len; TRACE_ENTER("WsfbScreenInit"); #if DEBUG ErrorF("\tbitsPerPixel=%d, depth=%d, defaultVisual=%s\n" - "\tmask: %x,%x,%x, offset: %d,%d,%d\n", + "\tmask: %x,%x,%x, offset: %u,%u,%u\n", pScrn->bitsPerPixel, pScrn->depth, xf86GetVisualName(pScrn->defaultVisual), @@ -628,6 +702,7 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #endif switch (fPtr->info.depth) { case 1: + case 4: case 8: len = fPtr->linebytes*fPtr->info.height; break; @@ -638,6 +713,13 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) len = fPtr->linebytes*fPtr->info.height; } break; + case 24: + if (fPtr->linebytes == fPtr->info.width) { + len = fPtr->info.width*fPtr->info.height*3; + } else { + len = fPtr->linebytes*fPtr->info.height; + } + break; case 32: if (fPtr->linebytes == fPtr->info.width) { len = fPtr->info.width*fPtr->info.height*sizeof(int); @@ -684,10 +766,20 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!miSetPixmapDepths()) return FALSE; - height = pScrn->virtualY; - width = pScrn->virtualX; + if (fPtr->rotate == WSFB_ROTATE_CW + || fPtr->rotate == WSFB_ROTATE_CCW) { + height = pScrn->virtualX; + width = pScrn->displayWidth = pScrn->virtualY; + } else { + height = pScrn->virtualY; + width = pScrn->virtualX; + } + if (fPtr->rotate && !fPtr->PointerMoved) { + fPtr->PointerMoved = pScrn->PointerMoved; + pScrn->PointerMoved = WsfbPointerMoved; + } - fPtr->fbstart = fPtr->fbmem; + fPtr->fbstart = fPtr->fbmem; switch (pScrn->bitsPerPixel) { case 1: @@ -704,6 +796,7 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) break; case 8: case 16: + case 24: case 32: ret = fbScreenInit(pScreen, fPtr->fbstart, @@ -736,25 +829,54 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } - if (pScrn->bitsPerPixel > 8) { + if (pScrn->bitsPerPixel >= 8) { if (!fbPictureInit(pScreen, NULL, 0)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "RENDER extension initialisation failed."); } if (fPtr->shadowFB) { + PixmapPtr pPixmap; + if (pScrn->bitsPerPixel < 8) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Shadow FB not available on < 8 depth"); } else { - if (!shadowInit(pScreen, shadowUpdatePackedWeak(), - WsfbWindowLinear)) - return FALSE; + ErrorF("XXX w %d h %d d %d\n", + pScreen->width, pScreen->height, + pScreen->rootDepth); + pPixmap = pScreen->CreatePixmap(pScreen, + pScreen->width, pScreen->height, + pScreen->rootDepth); + if (!pPixmap) + return FALSE; + if (!shadowSetup(pScreen) || + !shadowAdd(pScreen, pPixmap, + fPtr->rotate ? shadowUpdateRotatePackedWeak() : + shadowUpdatePackedWeak(), + WsfbWindowLinear, fPtr->rotate, NULL)) { + xf86DrvMsg(scrnIndex, X_ERROR, + "Shadow FB initialization failed\n"); + pScreen->DestroyPixmap(pPixmap); + return FALSE; + } } } #ifdef XFreeXDGA - WsfbDGAInit(pScrn, pScreen); + if (!fPtr->rotate) + WsfbDGAInit(pScrn, pScreen); + else + xf86DrvMsg(scrnIndex, X_INFO, "Rotated display, " + "disabling DGA\n"); #endif + if (fPtr->rotate) { + xf86DrvMsg(scrnIndex, X_INFO, "Enabling Driver Rotation, " + "disabling RandR\n"); + xf86DisableRandR(); + if (pScrn->bitsPerPixel == 24) + xf86DrvMsg(scrnIndex, X_WARNING, + "Rotation might be broken in 24 bpp\n"); + } xf86SetBlackWhitePixels(pScreen); miInitializeBackingStore(pScreen); @@ -766,8 +888,12 @@ WsfbScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) /* colormap */ if (!miCreateDefColormap(pScreen)) return FALSE; - flags = CMAP_RELOAD_ON_MODE_SWITCH; - if(!xf86HandleColormaps(pScreen, 256, 8, WsfbLoadPalette, + flags = CMAP_RELOAD_ON_MODE_SWITCH; + ncolors = fPtr->info.cmsize; + /* on StaticGray visuals, fake a 256 entries colormap */ + if (ncolors == 0) + ncolors = 256; + if(!xf86HandleColormaps(pScreen, ncolors, 8, WsfbLoadPalette, NULL, flags)) return FALSE; @@ -840,6 +966,44 @@ WsfbWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, return ((CARD8 *)fPtr->fbmem + row *fPtr->linebytes + offset); } +static void +WsfbPointerMoved(int index, int x, int y) +{ + ScrnInfoPtr pScrn = xf86Screens[index]; + WsfbPtr fPtr = WSFBPTR(pScrn); + int newX, newY; + + switch (fPtr->rotate) + { + case WSFB_ROTATE_CW: + /* 90 degrees CW rotation. */ + newX = pScrn->pScreen->height - y - 1; + newY = x; + break; + + case WSFB_ROTATE_CCW: + /* 90 degrees CCW rotation. */ + newX = y; + newY = pScrn->pScreen->width - x - 1; + break; + + case WSFB_ROTATE_UD: + /* 180 degrees UD rotation. */ + newX = pScrn->pScreen->width - x - 1; + newY = pScrn->pScreen->height - y - 1; + break; + + default: + /* No rotation. */ + newX = x; + newY = y; + break; + } + + /* Pass adjusted pointer coordinates to wrapped PointerMoved function. */ + (*fPtr->PointerMoved)(index, newX, newY); +} + static Bool WsfbEnterVT(int scrnIndex, int flags) { @@ -934,6 +1098,7 @@ WsfbLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, if (ioctl(fPtr->fd,WSDISPLAYIO_PUTCMAP, &cmap) == -1) ErrorF("ioctl FBIOPUTCMAP: %s\n", strerror(errno)); } + TRACE_EXIT("LoadPalette"); } static Bool @@ -964,11 +1129,12 @@ WsfbSave(ScrnInfoPtr pScrn) WsfbPtr fPtr = WSFBPTR(pScrn); TRACE_ENTER("WsfbSave"); + + if (fPtr->info.cmsize == 0) + return; + fPtr->saved_cmap.index = 0; - fPtr->saved_cmap.count = 256; - fPtr->saved_cmap.red = fPtr->saved_red; - fPtr->saved_cmap.green = fPtr->saved_green; - fPtr->saved_cmap.blue = fPtr->saved_blue; + fPtr->saved_cmap.count = fPtr->info.cmsize; if (ioctl(fPtr->fd, WSDISPLAYIO_GETCMAP, &(fPtr->saved_cmap)) == -1) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -985,16 +1151,14 @@ WsfbRestore(ScrnInfoPtr pScrn) TRACE_ENTER("WsfbRestore"); - /* reset colormap for text mode */ - fPtr->saved_cmap.index = 0; - fPtr->saved_cmap.count = 256; - fPtr->saved_cmap.red = fPtr->saved_red; - fPtr->saved_cmap.green = fPtr->saved_green; - fPtr->saved_cmap.blue = fPtr->saved_blue; - if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, - &(fPtr->saved_cmap)) == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "error restoring colormap %s\n", strerror(errno)); + if (fPtr->info.cmsize != 0) { + /* reset colormap for text mode */ + if (ioctl(fPtr->fd, WSDISPLAYIO_PUTCMAP, + &(fPtr->saved_cmap)) == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "error restoring colormap %s\n", + strerror(errno)); + } } /* Clear the screen */ |