Pull code from OpenBSD 4.0 version.

- rotation support
    - only allocate space for colormap save/restore at 8bpp
    - switch on render extension at 8bpp
This commit is contained in:
Matthieu Herrb
2006-12-03 18:07:02 +01:00
committed by Matthieu Herrb
parent ab847a95a8
commit b5d1de955b

View File

@@ -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 */