Add a new flag to ephyr, "-fakexa", which turns on an EXA acceleration

implementation that calls fb to get its work done. The purpose is to
    have a trusted EXA driver for use with testing changes to the core of
    EXA. However, fakexa has not received much testing yet, lacks offscreen
    pixmaps support, and doesn't reliably provide garbage when EXA doesn't
    get its syncing right. All of these should be fixed soon.
This commit is contained in:
Eric Anholt 2006-03-07 19:57:46 +00:00
parent 0a3d6c7399
commit 9d8c0e4bcb
5 changed files with 400 additions and 5 deletions

View File

@ -1,3 +1,20 @@
2006-03-07 Eric Anholt <anholt@FreeBSD.org>
* hw/kdrive/ephyr/Makefile.am:
* hw/kdrive/ephyr/ephyr.h:
* hw/kdrive/ephyr/ephyr_draw.c: (ephyrPrepareSolid), (ephyrSolid),
(ephyrDoneSolid), (ephyrPrepareCopy), (ephyrCopy), (ephyrDoneCopy),
(ephyrCheckComposite), (ephyrPrepareComposite), (ephyrComposite),
(ephyrDoneComposite), (ephyrMarkSync), (ephyrWaitMarker),
(ephyrDrawInit), (ephyrDrawEnable), (ephyrDrawDisable),
(ephyrDrawFini), (exaDDXDriverInit):
Add a new flag to ephyr, "-fakexa", which turns on an EXA acceleration
implementation that calls fb to get its work done. The purpose is to
have a trusted EXA driver for use with testing changes to the core of
EXA. However, fakexa has not received much testing yet, lacks offscreen
pixmaps support, and doesn't reliably provide garbage when EXA doesn't
get its syncing right. All of these should be fixed soon.
2006-03-07 Eric Anholt <anholt@FreeBSD.org>
* hw/xfree86/exa/exa.c:

View File

@ -1,6 +1,7 @@
INCLUDES = \
@KDRIVE_INCS@ \
@KDRIVE_CFLAGS@
@KDRIVE_CFLAGS@ \
-I$(srcdir)/../../../exa
noinst_LIBRARIES = libxephyr.a libxephyr-hostx.a
@ -13,6 +14,7 @@ bin_PROGRAMS = Xephyr
libxephyr_a_SOURCES = \
ephyr.c \
ephyr_draw.c \
os.c \
hostx.h \
ephyr.h
@ -32,11 +34,10 @@ Xephyr_LDADD = \
@KDRIVE_LIBS@ \
@KDRIVE_LIBS@ \
$(TSLIB_LIBS) \
@XEPHYR_LIBS@
@XEPHYR_LIBS@ \
../../../exa/libexa.la
Xephyr_DEPENDENCIES = \
libxephyr.a \
libxephyr-hostx.a \
@KDRIVE_LIBS@

View File

@ -33,6 +33,7 @@
#include "kdrive.h"
#include "kkeymap.h"
#include "hostx.h"
#include "exa.h"
#ifdef RANDR
#include "randrstr.h"
@ -45,11 +46,25 @@ typedef struct _ephyrPriv {
int bytes_per_line;
} EphyrPriv;
typedef struct _ephyrFakexaPriv {
ExaDriverRec exa;
Bool is_synced;
/* The following are arguments and other information from Prepare* calls
* which are stored for use in the inner calls.
*/
int op;
PicturePtr pSrcPicture, pMaskPicture, pDstPicture;
PixmapPtr pSrc, pDst;
GCPtr pGC;
} EphyrFakexaPriv;
typedef struct _ephyrScrPriv {
Rotation randr;
Bool shadow;
PixmapPtr pShadow;
DamagePtr pDamage;
EphyrFakexaPriv *fakexa;
} EphyrScrPriv;
extern KdCardFuncs ephyrFuncs;
@ -161,5 +176,18 @@ extern Bool ephyrCursorInit(ScreenPtr pScreen);
extern void ephyrCursorEnable(ScreenPtr pScreen);
/* ephyr_draw.c */
Bool
ephyrDrawInit(ScreenPtr pScreen);
void
ephyrDrawEnable(ScreenPtr pScreen);
void
ephyrDrawDisable(ScreenPtr pScreen);
void
ephyrDrawFini(ScreenPtr pScreen);
#endif

View File

@ -0,0 +1,340 @@
#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include "ephyr.h"
#include "exa_priv.h"
#include "fbpict.h"
#define EPHYR_TRACE_DRAW 0
#if EPHYR_TRACE_DRAW
#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
#else
#define TRACE_DRAW() do { } while (0)
#endif
/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
#define EPHYR_OFFSET_ALIGN 11
#define EPHYR_PITCH_ALIGN 9
#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
/**
* Sets up a scratch GC for fbFill, and saves other parameters for the
* ephyrSolid implementation.
*/
static Bool
ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
{
ScreenPtr pScreen = pPix->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
CARD32 tmpval[3];
fakexa->pDst = pPix;
fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
tmpval[0] = alu;
tmpval[1] = pm;
tmpval[2] = fg;
ChangeGC(fakexa->pGC, GCFunction | GCPlaneMask | GCForeground,
tmpval);
ValidateGC(&pPix->drawable, fakexa->pGC);
TRACE_DRAW();
return TRUE;
}
/**
* Does an fbFill of the rectangle to be drawn.
*/
static void
ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
{
ScreenPtr pScreen = pPix->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
}
/**
* Cleans up the scratch GC created in ephyrPrepareSolid.
*/
static void
ephyrDoneSolid(PixmapPtr pPix)
{
ScreenPtr pScreen = pPix->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
FreeScratchGC(fakexa->pGC);
}
/**
* Sets up a scratch GC for fbCopyArea, and saves other parameters for the
* ephyrCopy implementation.
*/
static Bool
ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
Pixel pm)
{
ScreenPtr pScreen = pDst->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
CARD32 tmpval[2];
fakexa->pSrc = pSrc;
fakexa->pDst = pDst;
fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
tmpval[0] = alu;
tmpval[1] = pm;
ChangeGC (fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
ValidateGC(&pDst->drawable, fakexa->pGC);
TRACE_DRAW();
return TRUE;
}
/**
* Does an fbCopyArea to take care of the requested copy.
*/
static void
ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
{
ScreenPtr pScreen = pDst->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
srcX, srcY, w, h, dstX, dstY);
}
/**
* Cleans up the scratch GC created in ephyrPrepareCopy.
*/
static void
ephyrDoneCopy(PixmapPtr pDst)
{
ScreenPtr pScreen = pDst->drawable.pScreen;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
FreeScratchGC (fakexa->pGC);
}
/**
* Reports that we can always accelerate the given operation. This may not be
* desirable from an EXA testing standpoint -- testing the fallback paths would
* be useful, too.
*/
static Bool
ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture)
{
return TRUE;
}
/**
* Saves off the parameters for ephyrComposite.
*/
static Bool
ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
PixmapPtr pDst)
{
KdScreenPriv(pDst->drawable.pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
op = op;
fakexa->pSrcPicture = pSrcPicture;
fakexa->pMaskPicture = pMaskPicture;
fakexa->pDstPicture = pDstPicture;
TRACE_DRAW();
return TRUE;
}
/**
* Does an fbComposite to complete the requested drawing operation.
*/
static void
ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int w, int h)
{
KdScreenPriv(pDst->drawable.pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
w, h);
}
static void
ephyrDoneComposite(PixmapPtr pDst)
{
}
/**
* In fakexa, we currently only track whether we have synced to the latest
* "accelerated" drawing that has happened or not. This will be used by an
* ephyrPrepareAccess for the purpose of reliably providing garbage when
* reading/writing when we haven't synced.
*/
static int
ephyrMarkSync(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
fakexa->is_synced = FALSE;
return 0;
}
/**
* Assumes that we're waiting on the latest marker. When EXA gets smarter and
* starts using markers in a fine-grained way (for example, waiting on drawing
* to required pixmaps to complete, rather than waiting for all drawing to
* complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
* implementation fine-grained as well.
*/
static void
ephyrWaitMarker(ScreenPtr pScreen, int marker)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
fakexa->is_synced = TRUE;
}
/**
* This function initializes EXA to use the fake acceleration implementation
* which just falls through to software. The purpose is to have a reliable,
* correct driver with which to test changes to the EXA core.
*/
Bool
ephyrDrawInit(ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
EphyrScrPriv *scrpriv = screen->driver;
EphyrFakexaPriv *fakexa;
Bool success;
fakexa = xcalloc(1, sizeof(*fakexa));
if (fakexa == NULL)
return FALSE;
#if 0
/* Currently, EXA isn't ready for what we want to do here. We want one
* pointer to the framebuffer (which is set in exaMapFramebuffer) to be
* considered "in framebuffer", and a separate pointer to offscreen memory,
* which is also considered to be in framebuffer. The alternative would be
* to extend the XImage data area set up in hostx.c from exaMapFramebuffer,
* but that may be complicated.
*/
fakexa->exa.card.memoryBase = xalloc(EPHYR_OFFSCREEN_SIZE);
if (fakexa->exa.card.memoryBase == NULL) {
xfree(fakexa);
return FALSE;
}
fakexa->exa.card.memorySize = EPHYR_OFFSCREEN_SIZE;
fakexa->exa.card.offScreenBase = EPHYR_OFFSCREEN_BASE;
#else
/* Tell EXA that there's a single framebuffer area, which happens to cover
* exactly what the front buffer is.
*/
fakexa->exa.card.memoryBase = screen->memory_base;
fakexa->exa.card.memorySize = screen->off_screen_base;
fakexa->exa.card.offScreenBase = screen->off_screen_base;
#endif
fakexa->exa.accel.PrepareSolid = ephyrPrepareSolid;
fakexa->exa.accel.Solid = ephyrSolid;
fakexa->exa.accel.DoneSolid = ephyrDoneSolid;
fakexa->exa.accel.PrepareCopy = ephyrPrepareCopy;
fakexa->exa.accel.Copy = ephyrCopy;
fakexa->exa.accel.DoneCopy = ephyrDoneCopy;
fakexa->exa.accel.CheckComposite = ephyrCheckComposite;
fakexa->exa.accel.PrepareComposite = ephyrPrepareComposite;
fakexa->exa.accel.Composite = ephyrComposite;
fakexa->exa.accel.DoneComposite = ephyrDoneComposite;
fakexa->exa.accel.MarkSync = ephyrMarkSync;
fakexa->exa.accel.WaitMarker = ephyrWaitMarker;
fakexa->exa.card.pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
fakexa->exa.card.pixmapPitchAlign = EPHYR_PITCH_ALIGN;
fakexa->exa.card.maxX = 1023;
fakexa->exa.card.maxY = 1023;
fakexa->exa.card.flags = EXA_OFFSCREEN_PIXMAPS;
success = exaDriverInit(pScreen, &fakexa->exa);
if (success) {
ErrorF("Initialized fake EXA acceleration\n");
scrpriv->fakexa = fakexa;
} else {
ErrorF("Failed to initialize EXA\n");
xfree(fakexa->exa.card.memoryBase);
xfree(fakexa);
}
return success;
}
void
ephyrDrawEnable(ScreenPtr pScreen)
{
}
void
ephyrDrawDisable(ScreenPtr pScreen)
{
}
void
ephyrDrawFini(ScreenPtr pScreen)
{
}
/**
* exaDDXDriverInit is required by the top-level EXA module, and is used by
* the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
* we won't be enabling/disabling the FB.
*/
void
exaDDXDriverInit(ScreenPtr pScreen)
{
}

View File

@ -62,6 +62,7 @@ ddxUseMsg (void)
ErrorF("-parent XID Use existing window as Xephyr root win\n");
ErrorF("-host-cursor Re-use exisiting X host server cursor\n");
ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n");
ErrorF("-fakexa Simulate acceleration using software rendering\n");
ErrorF("\n");
exit(1);
@ -93,6 +94,14 @@ ddxProcessArgument (int argc, char **argv, int i)
hostx_use_fullscreen();
return 1;
}
else if (!strcmp (argv[i], "-fakexa"))
{
ephyrFuncs.initAccel = ephyrDrawInit;
ephyrFuncs.enableAccel = ephyrDrawEnable;
ephyrFuncs.disableAccel = ephyrDrawDisable;
ephyrFuncs.finiAccel = ephyrDrawFini;
return 1;
}
else if (argv[i][0] == ':')
{
hostx_set_display_name(argv[i]);