Make Xephyr work without shadow fb

This commit is contained in:
Matthew Allum 2005-08-05 09:08:32 +00:00
parent fedbce2186
commit 4220a0c4cc
2 changed files with 412 additions and 314 deletions

View File

@ -1,6 +1,6 @@
/* /*
* Xephyr - A kdrive X server thats runs in a host X window. * Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@o-hand.com> * Authored by Matthew Allum <mallum@openedhand.com>
* *
* Copyright © 2004 Nokia * Copyright © 2004 Nokia
* *
@ -25,12 +25,7 @@
/* TODO: /* TODO:
* *
* POSSIBLES * o Support multiple screens, shouldn't be hard just alot of rejigging.
* - much improve keyboard handling *kind of done*
* - '-fullscreen' switch ?
* - full keyboard grab option somehow ? - use for testing WM key shortcuts
* with out host WM getting them instead.
* - Make cursor 'accel' better.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -115,7 +110,6 @@ ephyrScreenInitialize (KdScreenInfo *screen, EphyrScrPriv *scrpriv)
screen->fb[0].blueMask = 0x00; screen->fb[0].blueMask = 0x00;
screen->fb[0].depth = 8; screen->fb[0].depth = 8;
screen->fb[0].bitsPerPixel = 8; screen->fb[0].bitsPerPixel = 8;
} }
else else
{ {
@ -162,16 +156,20 @@ ephyrScreenInit (KdScreenInfo *screen)
EphyrScrPriv *scrpriv; EphyrScrPriv *scrpriv;
scrpriv = xalloc (sizeof (EphyrScrPriv)); scrpriv = xalloc (sizeof (EphyrScrPriv));
if (!scrpriv) if (!scrpriv)
return FALSE; return FALSE;
memset (scrpriv, 0, sizeof (EphyrScrPriv)); memset (scrpriv, 0, sizeof (EphyrScrPriv));
screen->driver = scrpriv; screen->driver = scrpriv;
if (!ephyrScreenInitialize (screen, scrpriv)) if (!ephyrScreenInitialize (screen, scrpriv))
{ {
screen->driver = 0; screen->driver = 0;
xfree (scrpriv); xfree (scrpriv);
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
@ -205,9 +203,6 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
EPHYR_DBG(" screen->width: %d, screen->height: %d", EPHYR_DBG(" screen->width: %d, screen->height: %d",
screen->width, screen->height); screen->width, screen->height);
/* Always use shadow so we get damage notifications */
scrpriv->shadow = TRUE;
KdComputeMouseMatrix (&m, scrpriv->randr, screen->width, screen->height); KdComputeMouseMatrix (&m, scrpriv->randr, screen->width, screen->height);
KdSetMouseMatrix (&m); KdSetMouseMatrix (&m);
@ -221,8 +216,26 @@ ephyrMapFramebuffer (KdScreenInfo *screen)
screen->memory_size = 0; screen->memory_size = 0;
screen->off_screen_base = 0; screen->off_screen_base = 0;
if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All))
{
scrpriv->shadow = FALSE;
screen->fb[0].byteStride = priv->bytes_per_line;
screen->fb[0].pixelStride = screen->width;
screen->fb[0].frameBuffer = (CARD8 *) (priv->base);
screen->off_screen_base = priv->bytes_per_line * screen->height;
}
else
{
/* Rotated/Reflected so we need to use shadow fb */
scrpriv->shadow = TRUE;
EPHYR_DBG("allocing shadow");
KdShadowFbAlloc (screen, 0, KdShadowFbAlloc (screen, 0,
scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)); scrpriv->randr & (RR_Rotate_90|RR_Rotate_270));
}
return TRUE; return TRUE;
} }
@ -252,6 +265,9 @@ ephyrSetScreenSizes (ScreenPtr pScreen)
Bool Bool
ephyrUnmapFramebuffer (KdScreenInfo *screen) ephyrUnmapFramebuffer (KdScreenInfo *screen)
{ {
EphyrScrPriv *scrpriv = screen->driver;
if (scrpriv->shadow)
KdShadowFbFree (screen, 0); KdShadowFbFree (screen, 0);
/* Note, priv->base will get freed when XImage recreated */ /* Note, priv->base will get freed when XImage recreated */
@ -261,42 +277,40 @@ ephyrUnmapFramebuffer (KdScreenInfo *screen)
void void
ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EPHYR_DBG("slow paint");
/* FIXME: Slow Rotated/Reflected updates could be much
* much faster efficiently updating via tranforming
* pBuf->pDamage regions
*/
shadowUpdateRotatePacked(pScreen, pBuf);
hostx_paint_rect(0,0,0,0, screen->width, screen->height);
}
static void
ephyrInternalDamageRedisplay (ScreenPtr pScreen)
{ {
KdScreenPriv(pScreen); KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen; KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver; EphyrScrPriv *scrpriv = screen->driver;
RegionPtr pRegion;
if (!scrpriv || !scrpriv->pDamage)
return;
pRegion = DamageRegion (scrpriv->pDamage);
if (REGION_NOTEMPTY (pScreen, pRegion))
{
int nbox; int nbox;
BoxPtr pbox; BoxPtr pbox;
RegionPtr damage; nbox = REGION_NUM_RECTS (pRegion);
pbox = REGION_RECTS (pRegion);
if (!(scrpriv->randr & RR_Rotate_0) || (scrpriv->randr & RR_Reflect_All))
{
/* Rotated.
* TODO: Fix this to use damage as well so much faster.
* Sledgehammer approach atm.
*
* Catch reflects here too - though thats wrong ...
*/
EPHYR_DBG("slow paint");
shadowUpdateRotatePacked(pScreen, pBuf);
hostx_paint_rect(0,0,0,0, screen->width, screen->height);
return;
}
else shadowUpdatePacked(pScreen, pBuf);
/* Figure out what rects have changed and update em. */
if (!pBuf || !pBuf->pDamage)
return;
damage = DamageRegion (pBuf->pDamage);
if (!REGION_NOTEMPTY (pScreen, damage))
return;
nbox = REGION_NUM_RECTS (damage);
pbox = REGION_RECTS (damage);
while (nbox--) while (nbox--)
{ {
@ -306,21 +320,68 @@ ephyrShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
pbox->y2 - pbox->y1); pbox->y2 - pbox->y1);
pbox++; pbox++;
} }
DamageEmpty (scrpriv->pDamage);
}
}
static void
ephyrInternalDamageBlockHandler (pointer data,
OSTimePtr pTimeout,
pointer pRead)
{
ScreenPtr pScreen = (ScreenPtr) data;
ephyrInternalDamageRedisplay (pScreen);
}
static void
ephyrInternalDamageWakeupHandler (pointer data, int i, pointer LastSelectMask)
{
/* FIXME: Not needed ? */
} }
Bool Bool
ephyrSetShadow (ScreenPtr pScreen) ephyrSetInternalDamage (ScreenPtr pScreen)
{ {
KdScreenPriv(pScreen); KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen; KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver; EphyrScrPriv *scrpriv = screen->driver;
ShadowUpdateProc update; PixmapPtr pPixmap = NULL;
ShadowWindowProc window;
window = ephyrWindowLinear; scrpriv->pDamage = DamageCreate ((DamageReportFunc) 0,
update = ephyrShadowUpdate; (DamageDestroyFunc) 0,
DamageReportNone,
TRUE,
pScreen,
pScreen);
return KdShadowSet (pScreen, scrpriv->randr, update, window); if (!RegisterBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
ephyrInternalDamageWakeupHandler,
(pointer) pScreen))
return FALSE;
pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
DamageRegister (&pPixmap->drawable, scrpriv->pDamage);
return TRUE;
}
void
ephyrUnsetInternalDamage (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
PixmapPtr pPixmap = NULL;
pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
DamageUnregister (&pPixmap->drawable, scrpriv->pDamage);
RemoveBlockAndWakeupHandlers (ephyrInternalDamageBlockHandler,
ephyrInternalDamageWakeupHandler,
(pointer) pScreen);
} }
#ifdef RANDR #ifdef RANDR
@ -397,10 +458,8 @@ ephyrRandRSetConfig (ScreenPtr pScreen,
EphyrScrPriv *scrpriv = screen->driver; EphyrScrPriv *scrpriv = screen->driver;
Bool wasEnabled = pScreenPriv->enabled; Bool wasEnabled = pScreenPriv->enabled;
EphyrScrPriv oldscr; EphyrScrPriv oldscr;
int oldwidth; int oldwidth, oldheight, oldmmwidth, oldmmheight;
int oldheight; Bool oldshadow;
int oldmmwidth;
int oldmmheight;
int newwidth, newheight; int newwidth, newheight;
if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) if (screen->randr & (RR_Rotate_0|RR_Rotate_180))
@ -423,6 +482,7 @@ ephyrRandRSetConfig (ScreenPtr pScreen,
oldheight = screen->height; oldheight = screen->height;
oldmmwidth = pScreen->mmWidth; oldmmwidth = pScreen->mmWidth;
oldmmheight = pScreen->mmHeight; oldmmheight = pScreen->mmHeight;
oldshadow = scrpriv->shadow;
/* /*
* Set new configuration * Set new configuration
@ -440,10 +500,30 @@ ephyrRandRSetConfig (ScreenPtr pScreen,
if (!ephyrMapFramebuffer (screen)) if (!ephyrMapFramebuffer (screen))
goto bail4; goto bail4;
KdShadowUnset (screen->pScreen); /* FIXME below should go in own call */
if (!ephyrSetShadow (screen->pScreen)) if (oldshadow)
KdShadowUnset (screen->pScreen);
else
ephyrUnsetInternalDamage(screen->pScreen);
if (scrpriv->shadow)
{
if (!KdShadowSet (screen->pScreen,
scrpriv->randr,
ephyrShadowUpdate,
ephyrWindowLinear))
goto bail4; goto bail4;
}
else
{
/* Without shadow fb ( non rotated ) we need
* to use damage to efficiently update display
* via signal regions what to copy from 'fb'.
*/
if (!ephyrSetInternalDamage(screen->pScreen))
goto bail4;
}
ephyrSetScreenSizes (screen->pScreen); ephyrSetScreenSizes (screen->pScreen);
@ -462,7 +542,6 @@ ephyrRandRSetConfig (ScreenPtr pScreen,
KdSetSubpixelOrder (pScreen, scrpriv->randr); KdSetSubpixelOrder (pScreen, scrpriv->randr);
if (wasEnabled) if (wasEnabled)
KdEnableScreen (pScreen); KdEnableScreen (pScreen);
@ -518,6 +597,9 @@ ephyrInitScreen (ScreenPtr pScreen)
Bool Bool
ephyrFinishInitScreen (ScreenPtr pScreen) ephyrFinishInitScreen (ScreenPtr pScreen)
{ {
/* FIXME: Calling this even if not using shadow.
* Seems harmless enough. But may be safer elsewhere.
*/
if (!shadowSetup (pScreen)) if (!shadowSetup (pScreen))
return FALSE; return FALSE;
@ -532,7 +614,19 @@ ephyrFinishInitScreen (ScreenPtr pScreen)
Bool Bool
ephyrCreateResources (ScreenPtr pScreen) ephyrCreateResources (ScreenPtr pScreen)
{ {
return ephyrSetShadow (pScreen); KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EPHYR_DBG("mark");
if (scrpriv->shadow)
return KdShadowSet (pScreen,
scrpriv->randr,
ephyrShadowUpdate,
ephyrWindowLinear);
else
return ephyrSetInternalDamage(pScreen);
} }
void void

View File

@ -47,6 +47,7 @@ typedef struct _ephyrScrPriv {
Rotation randr; Rotation randr;
Bool shadow; Bool shadow;
PixmapPtr pShadow; PixmapPtr pShadow;
DamagePtr pDamage;
} EphyrScrPriv; } EphyrScrPriv;
extern KdCardFuncs ephyrFuncs; extern KdCardFuncs ephyrFuncs;
@ -116,8 +117,11 @@ ephyrSetScreenSizes (ScreenPtr pScreen);
Bool Bool
ephyrUnmapFramebuffer (KdScreenInfo *screen); ephyrUnmapFramebuffer (KdScreenInfo *screen);
void
ephyrUnsetInternalDamage (ScreenPtr pScreen);
Bool Bool
ephyrSetShadow (ScreenPtr pScreen); ephyrSetInternalDamage (ScreenPtr pScreen);
Bool Bool
ephyrCreateColormap (ColormapPtr pmap); ephyrCreateColormap (ColormapPtr pmap);