summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c')
-rw-r--r--xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c517
1 files changed, 447 insertions, 70 deletions
diff --git a/xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c b/xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c
index f5225ca22..be4ad327c 100644
--- a/xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c
+++ b/xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c,v 1.11 2001/03/30 02:15:20 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/fbdev/fbdev.c,v 1.28 2001/07/24 19:06:03 keithp Exp $ */
#include "fbdev.h"
@@ -86,28 +86,67 @@ fbdevCardInit (KdCardInfo *card)
return TRUE;
}
+#define FBDEV_KLUDGE_FORMAT
+#ifdef FBDEV_KLUDGE_FORMAT
+static Pixel
+fbdevMakeContig (Pixel orig, Pixel others)
+{
+ Pixel low;
+
+ low = lowbit (orig) >> 1;
+ while (low && (others & low) == 0)
+ {
+ orig |= low;
+ low >>= 1;
+ }
+ return orig;
+}
+#endif
+
Bool
fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
{
FbdevPriv *priv = screen->card->driver;
Pixel allbits;
int depth;
- Bool rotate;
Bool shadow;
+ Bool gray;
#ifdef FAKE24_ON_16
Bool fake24;
#endif
depth = priv->var.bits_per_pixel;
+ gray = priv->var.grayscale;
switch (priv->fix.visual) {
case FB_VISUAL_PSEUDOCOLOR:
- screen->fb[0].visuals = ((1 << StaticGray) |
- (1 << GrayScale) |
- (1 << StaticColor) |
- (1 << PseudoColor) |
- (1 << TrueColor) |
- (1 << DirectColor));
+ if (gray)
+ {
+ screen->fb[0].visuals = (1 << StaticGray);
+ /* could also support GrayScale, but what's the point? */
+ }
+ else
+ {
+ screen->fb[0].visuals = ((1 << StaticGray) |
+ (1 << GrayScale) |
+ (1 << StaticColor) |
+ (1 << PseudoColor) |
+ (1 << TrueColor) |
+ (1 << DirectColor));
+ }
+ screen->fb[0].blueMask = 0x00;
+ screen->fb[0].greenMask = 0x00;
+ screen->fb[0].redMask = 0x00;
+ break;
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ if (gray)
+ {
+ screen->fb[0].visuals = (1 << StaticGray);
+ }
+ else
+ {
+ screen->fb[0].visuals = (1 << StaticColor);
+ }
screen->fb[0].blueMask = 0x00;
screen->fb[0].greenMask = 0x00;
screen->fb[0].redMask = 0x00;
@@ -119,11 +158,24 @@ fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
screen->fb[0].redMask = Mask (priv->var.red.offset, priv->var.red.length);
screen->fb[0].greenMask = Mask (priv->var.green.offset, priv->var.green.length);
screen->fb[0].blueMask = Mask (priv->var.blue.offset, priv->var.blue.length);
-#ifdef ITSY
- screen->fb[0].redMask = 0xf800;
- screen->fb[0].greenMask = 0x07e0;
- screen->fb[0].blueMask = 0x001f;
-#endif
+#ifdef FBDEV_KLUDGE_FORMAT
+ /*
+ * This is a kludge so that Render will work -- fill in the gaps
+ * in the pixel
+ */
+ screen->fb[0].redMask = fbdevMakeContig (screen->fb[0].redMask,
+ screen->fb[0].greenMask|
+ screen->fb[0].blueMask);
+
+ screen->fb[0].greenMask = fbdevMakeContig (screen->fb[0].greenMask,
+ screen->fb[0].redMask|
+ screen->fb[0].blueMask);
+
+ screen->fb[0].blueMask = fbdevMakeContig (screen->fb[0].blueMask,
+ screen->fb[0].redMask|
+ screen->fb[0].greenMask);
+
+#endif
allbits = screen->fb[0].redMask | screen->fb[0].greenMask | screen->fb[0].blueMask;
depth = 32;
while (depth && !(allbits & (1 << (depth - 1))))
@@ -134,15 +186,15 @@ fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
break;
}
screen->rate = 72;
- scrpriv->rotate = ((priv->var.xres < priv->var.yres) !=
- (screen->width < screen->height));
+ scrpriv->rotation = screen->rotation;
+
#ifdef FAKE24_ON_16
if (screen->fb[0].depth == 24 && screen->fb[0].bitsPerPixel == 24 &&
priv->var.bits_per_pixel == 16)
{
fake24 = TRUE;
scrpriv->shadow = TRUE;
- scrpriv->rotate = FALSE;
+ scrpriv->rotation = 0;
screen->fb[0].redMask = 0xff0000;
screen->fb[0].greenMask = 0x00ff00;
screen->fb[0].blueMask = 0x0000ff;
@@ -155,27 +207,13 @@ fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv)
{
screen->fb[0].depth = depth;
screen->fb[0].bitsPerPixel = priv->var.bits_per_pixel;
- if (!scrpriv->rotate)
- {
- screen->width = priv->var.xres;
- screen->height = priv->var.yres;
- screen->fb[0].byteStride = priv->fix.line_length;
- screen->fb[0].pixelStride = (priv->fix.line_length * 8 /
- priv->var.bits_per_pixel);
- screen->fb[0].frameBuffer = (CARD8 *) (priv->fb);
- return TRUE;
- }
- else
- {
- screen->width = priv->var.yres;
- screen->height = priv->var.xres;
- screen->softCursor = TRUE;
- }
+ screen->width = priv->var.xres;
+ screen->height = priv->var.yres;
+ screen->fb[0].byteStride = priv->fix.line_length;
+ screen->fb[0].pixelStride = (priv->fix.line_length * 8 /
+ priv->var.bits_per_pixel);
+ screen->fb[0].frameBuffer = (CARD8 *) (priv->fb);
}
- if (scrpriv->rotate)
- scrpriv->shadow = TRUE;
- if (scrpriv->shadow)
- return KdShadowScreenInit (screen);
return TRUE;
}
@@ -202,7 +240,8 @@ fbdevWindowLinear (ScreenPtr pScreen,
CARD32 row,
CARD32 offset,
int mode,
- CARD32 *size)
+ CARD32 *size,
+ void *closure)
{
KdScreenPriv(pScreen);
FbdevPriv *priv = pScreenPriv->card->driver;
@@ -295,18 +334,64 @@ fbdevUpdateFake24 (ScreenPtr pScreen,
}
#endif /* FAKE24_ON_16 */
-Bool
-fbdevInitScreen (ScreenPtr pScreen)
+LayerPtr
+fbdevLayerCreate (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
FbdevPriv *priv = pScreenPriv->card->driver;
- FbdevScrPriv *scrpriv = pScreenPriv->screen->driver;
+ FbdevScrPriv *scrpriv = screen->driver;
+ LayerPtr pLayer;
ShadowUpdateProc update;
ShadowWindowProc window;
+ PixmapPtr pPixmap;
+ int kind;
+ KdMouseMatrix m;
+ switch (scrpriv->rotation) {
+ case 0:
+ pScreen->width = screen->width;
+ pScreen->height = screen->height;
+ pScreen->mmWidth = screen->width_mm;
+ pScreen->mmHeight = screen->height_mm;
+ scrpriv->shadow = FALSE;
+ m.matrix[0][0] = 1; m.matrix[0][1] = 0; m.matrix[0][2] = 0;
+ m.matrix[1][0] = 0; m.matrix[1][1] = 1; m.matrix[1][2] = 0;
+ break;
+ case 90:
+ pScreen->width = screen->height;
+ pScreen->height = screen->width;
+ pScreen->mmWidth = screen->height_mm;
+ pScreen->mmHeight = screen->width_mm;
+ scrpriv->shadow = TRUE;
+ m.matrix[0][0] = 0; m.matrix[0][1] = -1; m.matrix[0][2] = screen->height - 1;
+ m.matrix[1][0] = 1; m.matrix[1][1] = 0; m.matrix[1][2] = 0;
+ break;
+ case 180:
+ pScreen->width = screen->width;
+ pScreen->height = screen->height;
+ pScreen->mmWidth = screen->width_mm;
+ pScreen->mmHeight = screen->height_mm;
+ scrpriv->shadow = TRUE;
+ m.matrix[0][0] = -1; m.matrix[0][1] = 0; m.matrix[0][2] = screen->width - 1;
+ m.matrix[1][0] = 0; m.matrix[1][1] = -1; m.matrix[1][2] = screen->height - 1;
+ break;
+ case 270:
+ pScreen->width = screen->height;
+ pScreen->height = screen->width;
+ pScreen->mmWidth = screen->height_mm;
+ pScreen->mmHeight = screen->width_mm;
+ scrpriv->shadow = TRUE;
+ m.matrix[0][0] = 0; m.matrix[0][1] = 1; m.matrix[0][2] = 0;
+ m.matrix[1][0] = -1; m.matrix[1][1] = 0; m.matrix[1][2] = screen->width - 1;
+ break;
+ }
+ KdSetMouseMatrix (&m);
+
if (scrpriv->shadow)
{
window = fbdevWindowLinear;
+ update = 0;
#ifdef FAKE24_ON_16
if (pScreenPriv->screen->fb[0].bitsPerPixel == 24 && priv->var.bits_per_pixel == 16)
{
@@ -315,25 +400,292 @@ fbdevInitScreen (ScreenPtr pScreen)
else
#endif /* FAKE24_ON_16 */
{
- update = shadowUpdatePacked;
- if (scrpriv->rotate)
- {
- window = fbdevWindowLinear;
- switch (pScreenPriv->screen->fb[0].bitsPerPixel) {
- case 8:
- update = shadowUpdateRotate8; break;
- case 16:
- update = shadowUpdateRotate16; break;
- case 32:
- update = shadowUpdateRotate32; break;
- }
- }
+ if (scrpriv->rotation)
+ update = shadowUpdateRotatePacked;
+ else
+ update = shadowUpdatePacked;
+ }
+ if (!update)
+ abort ();
+ kind = LAYER_SHADOW;
+ pPixmap = 0;
+ }
+ else
+ {
+ kind = LAYER_FB;
+ pPixmap = LAYER_SCREEN_PIXMAP;
+ update = 0;
+ window = 0;
+ }
+ return LayerCreate (pScreen, kind, screen->fb[0].depth,
+ pPixmap, update, window, scrpriv->rotation, 0);
+}
+
+
+#ifdef RANDR
+Bool
+fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevScrPriv *scrpriv = screen->driver;
+ RRVisualGroupPtr pVisualGroup;
+ RRGroupOfVisualGroupPtr pGroupOfVisualGroup;
+ RRScreenSizePtr pSize;
+ Rotation rotateKind;
+ int rotation;
+ int n;
+
+ *rotations = RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270;
+
+ for (n = 0; n < pScreen->numDepths; n++)
+ if (pScreen->allowedDepths[n].numVids)
+ break;
+ if (n == pScreen->numDepths)
+ return FALSE;
+
+ pVisualGroup = RRCreateVisualGroup (pScreen);
+ if (!pVisualGroup)
+ return FALSE;
+ if (!RRAddDepthToVisualGroup (pScreen,
+ pVisualGroup,
+ &pScreen->allowedDepths[n]))
+ {
+ RRDestroyVisualGroup (pScreen, pVisualGroup);
+ return FALSE;
+ }
+
+ pVisualGroup = RRRegisterVisualGroup (pScreen, pVisualGroup);
+ if (!pVisualGroup)
+ return FALSE;
+
+ pGroupOfVisualGroup = RRCreateGroupOfVisualGroup (pScreen);
+
+ if (!RRAddVisualGroupToGroupOfVisualGroup (pScreen,
+ pGroupOfVisualGroup,
+ pVisualGroup))
+ {
+ RRDestroyGroupOfVisualGroup (pScreen, pGroupOfVisualGroup);
+ /* pVisualGroup left until screen closed */
+ return FALSE;
+ }
+
+ pGroupOfVisualGroup = RRRegisterGroupOfVisualGroup (pScreen, pGroupOfVisualGroup);
+ if (!pGroupOfVisualGroup)
+ return FALSE;
+
+ pSize = RRRegisterSize (pScreen,
+ screen->width,
+ screen->height,
+ screen->width_mm,
+ screen->height_mm,
+ pGroupOfVisualGroup);
+
+ rotation = scrpriv->rotation - screen->rotation;
+ if (rotation < 0)
+ rotation += 360;
+
+ switch (rotation)
+ {
+ case 0:
+ rotateKind = RR_Rotate_0;
+ break;
+ case 90:
+ rotateKind = RR_Rotate_90;
+ break;
+ case 180:
+ rotateKind = RR_Rotate_180;
+ break;
+ case 270:
+ rotateKind = RR_Rotate_270;
+ break;
+ }
+
+ RRSetCurrentConfig (pScreen, rotateKind, pSize, pVisualGroup);
+
+ return TRUE;
+}
+
+int
+fbdevLayerAdd (WindowPtr pWin, pointer value)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ LayerPtr pLayer = (LayerPtr) value;
+
+ if (!LayerWindowAdd (pScreen, pLayer, pWin))
+ return WT_STOPWALKING;
+
+ return WT_WALKCHILDREN;
+}
+
+int
+fbdevLayerRemove (WindowPtr pWin, pointer value)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ LayerPtr pLayer = (LayerPtr) value;
+
+ LayerWindowRemove (pScreen, pLayer, pWin);
+
+ return WT_WALKCHILDREN;
+}
+
+fbdevRandRSetConfig (ScreenPtr pScreen,
+ Rotation rotateKind,
+ RRScreenSizePtr pSize,
+ RRVisualGroupPtr pVisualGroup)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ FbdevScrPriv *scrpriv = screen->driver;
+ int rotation;
+ Bool wasEnabled = pScreenPriv->enabled;
+
+ /*
+ * The only thing that can change is rotation
+ */
+ switch (rotateKind)
+ {
+ case RR_Rotate_0:
+ rotation = screen->rotation;
+ break;
+ case RR_Rotate_90:
+ rotation = screen->rotation + 90;
+ break;
+ case RR_Rotate_180:
+ rotation = screen->rotation + 180;
+ break;
+ case RR_Rotate_270:
+ rotation = screen->rotation + 270;
+ break;
+ }
+ if (rotation >= 360)
+ rotation -= 360;
+
+ if (scrpriv->rotation != rotation)
+ {
+ LayerPtr pNewLayer;
+ int kind;
+ int oldrotation = scrpriv->rotation;
+ int oldshadow = scrpriv->shadow;
+ int oldwidth = pScreen->width;
+ int oldheight = pScreen->height;
+ PixmapPtr pPixmap;
+
+ if (wasEnabled)
+ KdDisableScreen (pScreen);
+
+ scrpriv->rotation = rotation;
+ pNewLayer = fbdevLayerCreate (pScreen);
+ if (!pNewLayer)
+ {
+ scrpriv->shadow = oldshadow;
+ scrpriv->rotation = oldrotation;
+ }
+ if (WalkTree (pScreen, fbdevLayerAdd, (pointer) pNewLayer) == WT_STOPWALKING)
+ {
+ WalkTree (pScreen, fbdevLayerRemove, (pointer) pNewLayer);
+ LayerDestroy (pScreen, pNewLayer);
+ scrpriv->rotation = oldrotation;
+ scrpriv->shadow = oldshadow;
+ pScreen->width = oldwidth;
+ pScreen->height = oldheight;
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
+ return FALSE;
}
- return KdShadowInitScreen (pScreen, update, window);
+ WalkTree (pScreen, fbdevLayerRemove, (pointer) scrpriv->pLayer);
+ LayerDestroy (pScreen, scrpriv->pLayer);
+ scrpriv->pLayer = pNewLayer;
+ if (wasEnabled)
+ KdEnableScreen (pScreen);
}
return TRUE;
}
+Bool
+fbdevRandRInit (ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+
+ if (!RRScreenInit (pScreen))
+ return FALSE;
+
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = fbdevRandRGetInfo;
+ pScrPriv->rrSetConfig = fbdevRandRSetConfig;
+ return TRUE;
+}
+#endif
+
+Bool
+fbdevCreateColormap (ColormapPtr pmap)
+{
+ ScreenPtr pScreen = pmap->pScreen;
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ VisualPtr pVisual;
+ int i;
+ int nent;
+ xColorItem *pdefs;
+
+ switch (priv->fix.visual) {
+ case FB_VISUAL_STATIC_PSEUDOCOLOR:
+ pVisual = pmap->pVisual;
+ nent = pVisual->ColormapEntries;
+ pdefs = ALLOCATE_LOCAL (nent * sizeof (xColorItem));
+ if (!pdefs)
+ return FALSE;
+ for (i = 0; i < nent; i++)
+ pdefs[i].pixel = i;
+ fbdevGetColors (pScreen, 0, nent, pdefs);
+ for (i = 0; i < nent; i++)
+ {
+ pmap->red[i].co.local.red = pdefs[i].red;
+ pmap->red[i].co.local.green = pdefs[i].green;
+ pmap->red[i].co.local.blue = pdefs[i].blue;
+ }
+ DEALLOCATE_LOCAL (pdefs);
+ return TRUE;
+ default:
+ return fbInitializeColormap (pmap);
+ }
+}
+
+#ifdef TOUCHSCREEN
+int TsFbdev = -1;
+#endif
+
+Bool
+fbdevInitScreen (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ FbdevPriv *priv = pScreenPriv->card->driver;
+ FbdevScrPriv *scrpriv = pScreenPriv->screen->driver;
+ ShadowUpdateProc update;
+ ShadowWindowProc window;
+
+#ifdef TOUCHSCREEN
+ TsFbdev = pScreen->myNum;
+#endif
+
+ pScreen->CreateColormap = fbdevCreateColormap;
+
+ if (!LayerStartInit (pScreen))
+ return FALSE;
+ if (!LayerFinishInit (pScreen))
+ return FALSE;
+ scrpriv->pLayer = fbdevLayerCreate (pScreen);
+ if (!scrpriv->pLayer)
+ return FALSE;
+#ifdef RANDR
+ if (!fbdevRandRInit (pScreen))
+ return FALSE;
+#endif
+ return TRUE;
+}
+
void
fbdevPreserve (KdCardInfo *card)
{
@@ -343,10 +695,10 @@ Bool
fbdevEnable (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
- FbdevPriv *priv = pScreenPriv->card->driver;
+ KdScreenInfo *screen = pScreenPriv->screen;
+ FbdevPriv *priv = pScreenPriv->card->driver;
FbdevScrPriv *scrpriv = pScreenPriv->screen->driver;
int k;
- KdMouseMatrix m;
priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL;
@@ -357,16 +709,7 @@ fbdevEnable (ScreenPtr pScreen)
perror ("FBIOPUT_VSCREENINFO");
return FALSE;
}
- if (scrpriv->rotate)
- {
- m.matrix[0][0] = 0; m.matrix[0][1] = 1; m.matrix[0][2] = 0;
- m.matrix[1][0] = -1; m.matrix[1][1] = 0; m.matrix[1][2] = pScreen->height - 1;
- }
- else
- {
- m.matrix[0][0] = 1; m.matrix[0][1] = 0; m.matrix[0][2] = 0;
- m.matrix[1][0] = 0; m.matrix[1][1] = 1; m.matrix[1][2] = 0;
- }
+
if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR)
{
struct fb_cmap cmap;
@@ -389,7 +732,6 @@ fbdevEnable (ScreenPtr pScreen)
cmap.transp = 0;
ioctl (priv->fd, FBIOPUTCMAP, &cmap);
}
- KdSetMouseMatrix (&m);
return TRUE;
}
@@ -398,14 +740,23 @@ fbdevDPMS (ScreenPtr pScreen, int mode)
{
KdScreenPriv(pScreen);
FbdevPriv *priv = pScreenPriv->card->driver;
+ static int oldmode = -1;
+ if (mode == oldmode)
+ return TRUE;
#ifdef FBIOPUT_POWERMODE
if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0)
+ {
+ oldmode = mode;
return TRUE;
+ }
#endif
#ifdef FBIOBLANK
if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0)
+ {
+ oldmode = mode;
return TRUE;
+ }
#endif
return FALSE;
}
@@ -424,9 +775,6 @@ void
fbdevScreenFini (KdScreenInfo *screen)
{
FbdevScrPriv *scrpriv = screen->driver;
-
- if (scrpriv->shadow)
- KdShadowScreenFini (screen);
}
void
@@ -512,3 +860,32 @@ fbdevPutColors (ScreenPtr pScreen, int fb, int n, xColorItem *pdefs)
cmap.transp = 0;
ioctl (priv->fd, FBIOPUTCMAP, &cmap);
}
+
+
+KdCardFuncs fbdevFuncs = {
+ fbdevCardInit, /* cardinit */
+ fbdevScreenInit, /* scrinit */
+ fbdevInitScreen, /* initScreen */
+ fbdevPreserve, /* preserve */
+ fbdevEnable, /* enable */
+ fbdevDPMS, /* dpms */
+ fbdevDisable, /* disable */
+ fbdevRestore, /* restore */
+ fbdevScreenFini, /* scrfini */
+ fbdevCardFini, /* cardfini */
+
+ 0, /* initCursor */
+ 0, /* enableCursor */
+ 0, /* disableCursor */
+ 0, /* finiCursor */
+ 0, /* recolorCursor */
+
+ 0, /* initAccel */
+ 0, /* enableAccel */
+ 0, /* syncAccel */
+ 0, /* disableAccel */
+ 0, /* finiAccel */
+
+ fbdevGetColors, /* getColors */
+ fbdevPutColors, /* putColors */
+};