105b261ecSmrg/*
235c4bbdfSmrg * Copyright © 2006 Intel Corporation
305b261ecSmrg *
405b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a
505b261ecSmrg * copy of this software and associated documentation files (the "Software"),
605b261ecSmrg * to deal in the Software without restriction, including without limitation
705b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
805b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the
905b261ecSmrg * Software is furnished to do so, subject to the following conditions:
1005b261ecSmrg *
1105b261ecSmrg * The above copyright notice and this permission notice (including the next
1205b261ecSmrg * paragraph) shall be included in all copies or substantial portions of the
1305b261ecSmrg * Software.
1405b261ecSmrg *
1505b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1605b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1705b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1805b261ecSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1905b261ecSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2005b261ecSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2105b261ecSmrg * SOFTWARE.
2205b261ecSmrg *
2305b261ecSmrg * Authors:
2405b261ecSmrg *    Eric Anholt <eric@anholt.net>
2505b261ecSmrg *
2605b261ecSmrg */
2705b261ecSmrg
281b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H
291b5d61b8Smrg#include <dix-config.h>
3005b261ecSmrg#endif
3105b261ecSmrg
3205b261ecSmrg#include "ephyr.h"
3305b261ecSmrg#include "exa_priv.h"
3405b261ecSmrg#include "fbpict.h"
3505b261ecSmrg
3605b261ecSmrg#define EPHYR_TRACE_DRAW 0
3705b261ecSmrg
3805b261ecSmrg#if EPHYR_TRACE_DRAW
3905b261ecSmrg#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
4005b261ecSmrg#else
4105b261ecSmrg#define TRACE_DRAW() do { } while (0)
4205b261ecSmrg#endif
4305b261ecSmrg
4405b261ecSmrg/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
4505b261ecSmrg#define EPHYR_OFFSET_ALIGN	24
4605b261ecSmrg#define EPHYR_PITCH_ALIGN	24
4705b261ecSmrg
4805b261ecSmrg#define EPHYR_OFFSCREEN_SIZE	(16 * 1024 * 1024)
4905b261ecSmrg#define EPHYR_OFFSCREEN_BASE	(1 * 1024 * 1024)
5005b261ecSmrg
5105b261ecSmrg/**
5205b261ecSmrg * Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
5305b261ecSmrg * fb functions.
5405b261ecSmrg */
5505b261ecSmrgstatic void
5605b261ecSmrgephyrPreparePipelinedAccess(PixmapPtr pPix, int index)
5705b261ecSmrg{
5805b261ecSmrg    KdScreenPriv(pPix->drawable.pScreen);
5905b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
6005b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
6105b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
6205b261ecSmrg
6305b261ecSmrg    assert(fakexa->saved_ptrs[index] == NULL);
6405b261ecSmrg    fakexa->saved_ptrs[index] = pPix->devPrivate.ptr;
6505b261ecSmrg
6605b261ecSmrg    if (pPix->devPrivate.ptr != NULL)
6735c4bbdfSmrg        return;
6805b261ecSmrg
6905b261ecSmrg    pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix);
7005b261ecSmrg}
7105b261ecSmrg
7205b261ecSmrg/**
7305b261ecSmrg * Restores the original devPrivate.ptr of the pixmap from before we messed with
7405b261ecSmrg * it.
7505b261ecSmrg */
7605b261ecSmrgstatic void
7705b261ecSmrgephyrFinishPipelinedAccess(PixmapPtr pPix, int index)
7805b261ecSmrg{
7905b261ecSmrg    KdScreenPriv(pPix->drawable.pScreen);
8005b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
8105b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
8205b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
8305b261ecSmrg
8405b261ecSmrg    pPix->devPrivate.ptr = fakexa->saved_ptrs[index];
8505b261ecSmrg    fakexa->saved_ptrs[index] = NULL;
8605b261ecSmrg}
8705b261ecSmrg
8805b261ecSmrg/**
8905b261ecSmrg * Sets up a scratch GC for fbFill, and saves other parameters for the
9005b261ecSmrg * ephyrSolid implementation.
9105b261ecSmrg */
9205b261ecSmrgstatic Bool
9305b261ecSmrgephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
9405b261ecSmrg{
9505b261ecSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
9635c4bbdfSmrg
9705b261ecSmrg    KdScreenPriv(pScreen);
9805b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
9905b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
10005b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
1016747b715Smrg    ChangeGCVal tmpval[3];
10205b261ecSmrg
10305b261ecSmrg    ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST);
10405b261ecSmrg
10505b261ecSmrg    fakexa->pDst = pPix;
10605b261ecSmrg    fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
10705b261ecSmrg
1086747b715Smrg    tmpval[0].val = alu;
1096747b715Smrg    tmpval[1].val = pm;
1106747b715Smrg    tmpval[2].val = fg;
11135c4bbdfSmrg    ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground,
11235c4bbdfSmrg             tmpval);
11305b261ecSmrg
11405b261ecSmrg    ValidateGC(&pPix->drawable, fakexa->pGC);
11505b261ecSmrg
11605b261ecSmrg    TRACE_DRAW();
11705b261ecSmrg
11805b261ecSmrg    return TRUE;
11905b261ecSmrg}
12005b261ecSmrg
12105b261ecSmrg/**
12205b261ecSmrg * Does an fbFill of the rectangle to be drawn.
12305b261ecSmrg */
12405b261ecSmrgstatic void
12505b261ecSmrgephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
12605b261ecSmrg{
12705b261ecSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
12835c4bbdfSmrg
12905b261ecSmrg    KdScreenPriv(pScreen);
13005b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
13105b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
13205b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
13305b261ecSmrg
13405b261ecSmrg    fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
13505b261ecSmrg}
13605b261ecSmrg
13705b261ecSmrg/**
13805b261ecSmrg * Cleans up the scratch GC created in ephyrPrepareSolid.
13905b261ecSmrg */
14005b261ecSmrgstatic void
14105b261ecSmrgephyrDoneSolid(PixmapPtr pPix)
14205b261ecSmrg{
14305b261ecSmrg    ScreenPtr pScreen = pPix->drawable.pScreen;
14435c4bbdfSmrg
14505b261ecSmrg    KdScreenPriv(pScreen);
14605b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
14705b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
14805b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
14905b261ecSmrg
15005b261ecSmrg    FreeScratchGC(fakexa->pGC);
15105b261ecSmrg
15205b261ecSmrg    ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
15305b261ecSmrg}
15405b261ecSmrg
15505b261ecSmrg/**
15605b261ecSmrg * Sets up a scratch GC for fbCopyArea, and saves other parameters for the
15705b261ecSmrg * ephyrCopy implementation.
15805b261ecSmrg */
15905b261ecSmrgstatic Bool
16005b261ecSmrgephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
16135c4bbdfSmrg                 Pixel pm)
16205b261ecSmrg{
16305b261ecSmrg    ScreenPtr pScreen = pDst->drawable.pScreen;
16435c4bbdfSmrg
16505b261ecSmrg    KdScreenPriv(pScreen);
16605b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
16705b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
16805b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
1696747b715Smrg    ChangeGCVal tmpval[2];
17005b261ecSmrg
17105b261ecSmrg    ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
17205b261ecSmrg    ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
17305b261ecSmrg
17405b261ecSmrg    fakexa->pSrc = pSrc;
17505b261ecSmrg    fakexa->pDst = pDst;
17605b261ecSmrg    fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
17705b261ecSmrg
1786747b715Smrg    tmpval[0].val = alu;
1796747b715Smrg    tmpval[1].val = pm;
18035c4bbdfSmrg    ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
18105b261ecSmrg
18205b261ecSmrg    ValidateGC(&pDst->drawable, fakexa->pGC);
18305b261ecSmrg
18405b261ecSmrg    TRACE_DRAW();
18505b261ecSmrg
18605b261ecSmrg    return TRUE;
18705b261ecSmrg}
18805b261ecSmrg
18905b261ecSmrg/**
19005b261ecSmrg * Does an fbCopyArea to take care of the requested copy.
19105b261ecSmrg */
19205b261ecSmrgstatic void
19305b261ecSmrgephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
19405b261ecSmrg{
19505b261ecSmrg    ScreenPtr pScreen = pDst->drawable.pScreen;
19635c4bbdfSmrg
19705b261ecSmrg    KdScreenPriv(pScreen);
19805b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
19905b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
20005b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
20105b261ecSmrg
20205b261ecSmrg    fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
20335c4bbdfSmrg               srcX, srcY, w, h, dstX, dstY);
20405b261ecSmrg}
20505b261ecSmrg
20605b261ecSmrg/**
20705b261ecSmrg * Cleans up the scratch GC created in ephyrPrepareCopy.
20805b261ecSmrg */
20905b261ecSmrgstatic void
21005b261ecSmrgephyrDoneCopy(PixmapPtr pDst)
21105b261ecSmrg{
21205b261ecSmrg    ScreenPtr pScreen = pDst->drawable.pScreen;
21335c4bbdfSmrg
21405b261ecSmrg    KdScreenPriv(pScreen);
21505b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
21605b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
21705b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
21805b261ecSmrg
21935c4bbdfSmrg    FreeScratchGC(fakexa->pGC);
22005b261ecSmrg
22105b261ecSmrg    ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
22205b261ecSmrg    ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
22305b261ecSmrg}
22405b261ecSmrg
22505b261ecSmrg/**
22605b261ecSmrg * Reports that we can always accelerate the given operation.  This may not be
22705b261ecSmrg * desirable from an EXA testing standpoint -- testing the fallback paths would
22805b261ecSmrg * be useful, too.
22905b261ecSmrg */
23005b261ecSmrgstatic Bool
23105b261ecSmrgephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
23235c4bbdfSmrg                    PicturePtr pDstPicture)
23305b261ecSmrg{
23405b261ecSmrg    /* Exercise the component alpha helper, so fail on this case like a normal
23505b261ecSmrg     * driver
23605b261ecSmrg     */
23705b261ecSmrg    if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver)
23835c4bbdfSmrg        return FALSE;
23905b261ecSmrg
24005b261ecSmrg    return TRUE;
24105b261ecSmrg}
24205b261ecSmrg
24305b261ecSmrg/**
24405b261ecSmrg * Saves off the parameters for ephyrComposite.
24505b261ecSmrg */
24605b261ecSmrgstatic Bool
24705b261ecSmrgephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
24835c4bbdfSmrg                      PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
24935c4bbdfSmrg                      PixmapPtr pDst)
25005b261ecSmrg{
25105b261ecSmrg    KdScreenPriv(pDst->drawable.pScreen);
25205b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
25305b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
25405b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
25505b261ecSmrg
25605b261ecSmrg    ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
2571b5d61b8Smrg    if (pSrc != NULL)
2581b5d61b8Smrg        ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
25905b261ecSmrg    if (pMask != NULL)
26035c4bbdfSmrg        ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK);
26105b261ecSmrg
26205b261ecSmrg    fakexa->op = op;
26305b261ecSmrg    fakexa->pSrcPicture = pSrcPicture;
26405b261ecSmrg    fakexa->pMaskPicture = pMaskPicture;
26505b261ecSmrg    fakexa->pDstPicture = pDstPicture;
26605b261ecSmrg    fakexa->pSrc = pSrc;
26705b261ecSmrg    fakexa->pMask = pMask;
26805b261ecSmrg    fakexa->pDst = pDst;
26905b261ecSmrg
27005b261ecSmrg    TRACE_DRAW();
27105b261ecSmrg
27205b261ecSmrg    return TRUE;
27305b261ecSmrg}
27405b261ecSmrg
27505b261ecSmrg/**
27605b261ecSmrg * Does an fbComposite to complete the requested drawing operation.
27705b261ecSmrg */
27805b261ecSmrgstatic void
27905b261ecSmrgephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
28035c4bbdfSmrg               int dstX, int dstY, int w, int h)
28105b261ecSmrg{
28205b261ecSmrg    KdScreenPriv(pDst->drawable.pScreen);
28305b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
28405b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
28505b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
28605b261ecSmrg
28705b261ecSmrg    fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
28835c4bbdfSmrg                fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
28935c4bbdfSmrg                w, h);
29005b261ecSmrg}
29105b261ecSmrg
29205b261ecSmrgstatic void
29305b261ecSmrgephyrDoneComposite(PixmapPtr pDst)
29405b261ecSmrg{
29505b261ecSmrg    KdScreenPriv(pDst->drawable.pScreen);
29605b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
29705b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
29805b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
29905b261ecSmrg
30005b261ecSmrg    if (fakexa->pMask != NULL)
30135c4bbdfSmrg        ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK);
3021b5d61b8Smrg    if (fakexa->pSrc != NULL)
3031b5d61b8Smrg        ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
30405b261ecSmrg    ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
30505b261ecSmrg}
30605b261ecSmrg
30705b261ecSmrg/**
30805b261ecSmrg * Does fake acceleration of DownloadFromScren using memcpy.
30905b261ecSmrg */
31005b261ecSmrgstatic Bool
31105b261ecSmrgephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
31235c4bbdfSmrg                        int dst_pitch)
31305b261ecSmrg{
31405b261ecSmrg    KdScreenPriv(pSrc->drawable.pScreen);
31505b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
31605b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
31705b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
3184642e01fSmrg    unsigned char *src;
31905b261ecSmrg    int src_pitch, cpp;
32005b261ecSmrg
32105b261ecSmrg    if (pSrc->drawable.bitsPerPixel < 8)
32235c4bbdfSmrg        return FALSE;
32305b261ecSmrg
32405b261ecSmrg    ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
32505b261ecSmrg
32605b261ecSmrg    cpp = pSrc->drawable.bitsPerPixel / 8;
32705b261ecSmrg    src_pitch = exaGetPixmapPitch(pSrc);
32805b261ecSmrg    src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc);
32905b261ecSmrg    src += y * src_pitch + x * cpp;
33005b261ecSmrg
33105b261ecSmrg    for (; h > 0; h--) {
33235c4bbdfSmrg        memcpy(dst, src, w * cpp);
33335c4bbdfSmrg        dst += dst_pitch;
33435c4bbdfSmrg        src += src_pitch;
33505b261ecSmrg    }
33605b261ecSmrg
33705b261ecSmrg    exaMarkSync(pSrc->drawable.pScreen);
33805b261ecSmrg
33905b261ecSmrg    ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC);
34005b261ecSmrg
34105b261ecSmrg    return TRUE;
34205b261ecSmrg}
34305b261ecSmrg
34405b261ecSmrg/**
34505b261ecSmrg * Does fake acceleration of UploadToScreen using memcpy.
34605b261ecSmrg */
34705b261ecSmrgstatic Bool
34805b261ecSmrgephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
34935c4bbdfSmrg                    int src_pitch)
35005b261ecSmrg{
35105b261ecSmrg    KdScreenPriv(pDst->drawable.pScreen);
35205b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
35305b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
35405b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
3554642e01fSmrg    unsigned char *dst;
35605b261ecSmrg    int dst_pitch, cpp;
35705b261ecSmrg
35805b261ecSmrg    if (pDst->drawable.bitsPerPixel < 8)
35935c4bbdfSmrg        return FALSE;
36005b261ecSmrg
36105b261ecSmrg    ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
36205b261ecSmrg
36305b261ecSmrg    cpp = pDst->drawable.bitsPerPixel / 8;
36405b261ecSmrg    dst_pitch = exaGetPixmapPitch(pDst);
36505b261ecSmrg    dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
36605b261ecSmrg    dst += y * dst_pitch + x * cpp;
36705b261ecSmrg
36805b261ecSmrg    for (; h > 0; h--) {
36935c4bbdfSmrg        memcpy(dst, src, w * cpp);
37035c4bbdfSmrg        dst += dst_pitch;
37135c4bbdfSmrg        src += src_pitch;
37205b261ecSmrg    }
37305b261ecSmrg
37405b261ecSmrg    exaMarkSync(pDst->drawable.pScreen);
37505b261ecSmrg
37605b261ecSmrg    ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);
37705b261ecSmrg
37805b261ecSmrg    return TRUE;
37905b261ecSmrg}
38005b261ecSmrg
38105b261ecSmrgstatic Bool
38205b261ecSmrgephyrPrepareAccess(PixmapPtr pPix, int index)
38305b261ecSmrg{
38405b261ecSmrg    /* Make sure we don't somehow end up with a pointer that is in framebuffer
38505b261ecSmrg     * and hasn't been readied for us.
38605b261ecSmrg     */
38705b261ecSmrg    assert(pPix->devPrivate.ptr != NULL);
38805b261ecSmrg
38905b261ecSmrg    return TRUE;
39005b261ecSmrg}
39105b261ecSmrg
39205b261ecSmrg/**
39305b261ecSmrg * In fakexa, we currently only track whether we have synced to the latest
39405b261ecSmrg * "accelerated" drawing that has happened or not.  It's not used for anything
39505b261ecSmrg * yet.
39605b261ecSmrg */
39705b261ecSmrgstatic int
39805b261ecSmrgephyrMarkSync(ScreenPtr pScreen)
39905b261ecSmrg{
40005b261ecSmrg    KdScreenPriv(pScreen);
40105b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
40205b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
40305b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
40405b261ecSmrg
40505b261ecSmrg    fakexa->is_synced = FALSE;
40605b261ecSmrg
40705b261ecSmrg    return 0;
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrg/**
41105b261ecSmrg * Assumes that we're waiting on the latest marker.  When EXA gets smarter and
41205b261ecSmrg * starts using markers in a fine-grained way (for example, waiting on drawing
41305b261ecSmrg * to required pixmaps to complete, rather than waiting for all drawing to
41405b261ecSmrg * complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
41505b261ecSmrg * implementation fine-grained as well.
41605b261ecSmrg */
41705b261ecSmrgstatic void
41805b261ecSmrgephyrWaitMarker(ScreenPtr pScreen, int marker)
41905b261ecSmrg{
42005b261ecSmrg    KdScreenPriv(pScreen);
42105b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
42205b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
42305b261ecSmrg    EphyrFakexaPriv *fakexa = scrpriv->fakexa;
42405b261ecSmrg
42505b261ecSmrg    fakexa->is_synced = TRUE;
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrg/**
42905b261ecSmrg * This function initializes EXA to use the fake acceleration implementation
43005b261ecSmrg * which just falls through to software.  The purpose is to have a reliable,
43105b261ecSmrg * correct driver with which to test changes to the EXA core.
43205b261ecSmrg */
43305b261ecSmrgBool
43405b261ecSmrgephyrDrawInit(ScreenPtr pScreen)
43505b261ecSmrg{
43605b261ecSmrg    KdScreenPriv(pScreen);
43705b261ecSmrg    KdScreenInfo *screen = pScreenPriv->screen;
43805b261ecSmrg    EphyrScrPriv *scrpriv = screen->driver;
4396747b715Smrg    EphyrPriv *priv = screen->card->driver;
44005b261ecSmrg    EphyrFakexaPriv *fakexa;
44105b261ecSmrg    Bool success;
44205b261ecSmrg
4436747b715Smrg    fakexa = calloc(1, sizeof(*fakexa));
44405b261ecSmrg    if (fakexa == NULL)
44535c4bbdfSmrg        return FALSE;
44605b261ecSmrg
44705b261ecSmrg    fakexa->exa = exaDriverAlloc();
44805b261ecSmrg    if (fakexa->exa == NULL) {
44935c4bbdfSmrg        free(fakexa);
45035c4bbdfSmrg        return FALSE;
45105b261ecSmrg    }
45205b261ecSmrg
4536747b715Smrg    fakexa->exa->memoryBase = (CARD8 *) (priv->base);
4546747b715Smrg    fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen);
4556747b715Smrg    fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height;
45605b261ecSmrg
45705b261ecSmrg    /* Since we statically link against EXA, we shouldn't have to be smart about
45805b261ecSmrg     * versioning.
45905b261ecSmrg     */
46005b261ecSmrg    fakexa->exa->exa_major = 2;
46105b261ecSmrg    fakexa->exa->exa_minor = 0;
46205b261ecSmrg
46305b261ecSmrg    fakexa->exa->PrepareSolid = ephyrPrepareSolid;
46405b261ecSmrg    fakexa->exa->Solid = ephyrSolid;
46505b261ecSmrg    fakexa->exa->DoneSolid = ephyrDoneSolid;
46605b261ecSmrg
46705b261ecSmrg    fakexa->exa->PrepareCopy = ephyrPrepareCopy;
46805b261ecSmrg    fakexa->exa->Copy = ephyrCopy;
46905b261ecSmrg    fakexa->exa->DoneCopy = ephyrDoneCopy;
47005b261ecSmrg
47105b261ecSmrg    fakexa->exa->CheckComposite = ephyrCheckComposite;
47205b261ecSmrg    fakexa->exa->PrepareComposite = ephyrPrepareComposite;
47305b261ecSmrg    fakexa->exa->Composite = ephyrComposite;
47405b261ecSmrg    fakexa->exa->DoneComposite = ephyrDoneComposite;
47505b261ecSmrg
47605b261ecSmrg    fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen;
47705b261ecSmrg    fakexa->exa->UploadToScreen = ephyrUploadToScreen;
47805b261ecSmrg
47905b261ecSmrg    fakexa->exa->MarkSync = ephyrMarkSync;
48005b261ecSmrg    fakexa->exa->WaitMarker = ephyrWaitMarker;
48105b261ecSmrg
48205b261ecSmrg    fakexa->exa->PrepareAccess = ephyrPrepareAccess;
48305b261ecSmrg
48405b261ecSmrg    fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
48505b261ecSmrg    fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN;
48605b261ecSmrg
48705b261ecSmrg    fakexa->exa->maxX = 1023;
48805b261ecSmrg    fakexa->exa->maxY = 1023;
48905b261ecSmrg
49005b261ecSmrg    fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS;
49105b261ecSmrg
49205b261ecSmrg    success = exaDriverInit(pScreen, fakexa->exa);
49305b261ecSmrg    if (success) {
49435c4bbdfSmrg        ErrorF("Initialized fake EXA acceleration\n");
49535c4bbdfSmrg        scrpriv->fakexa = fakexa;
49635c4bbdfSmrg    }
49735c4bbdfSmrg    else {
49835c4bbdfSmrg        ErrorF("Failed to initialize EXA\n");
49935c4bbdfSmrg        free(fakexa->exa);
50035c4bbdfSmrg        free(fakexa);
50105b261ecSmrg    }
50205b261ecSmrg
50305b261ecSmrg    return success;
50405b261ecSmrg}
50505b261ecSmrg
50605b261ecSmrgvoid
50705b261ecSmrgephyrDrawEnable(ScreenPtr pScreen)
50805b261ecSmrg{
50905b261ecSmrg}
51005b261ecSmrg
51105b261ecSmrgvoid
51205b261ecSmrgephyrDrawDisable(ScreenPtr pScreen)
51305b261ecSmrg{
51405b261ecSmrg}
51505b261ecSmrg
51605b261ecSmrgvoid
51705b261ecSmrgephyrDrawFini(ScreenPtr pScreen)
51805b261ecSmrg{
51905b261ecSmrg}
52005b261ecSmrg
52105b261ecSmrg/**
52205b261ecSmrg * exaDDXDriverInit is required by the top-level EXA module, and is used by
52305b261ecSmrg * the xorg DDX to hook in its EnableDisableFB wrapper.  We don't need it, since
52405b261ecSmrg * we won't be enabling/disabling the FB.
52505b261ecSmrg */
52605b261ecSmrgvoid
52705b261ecSmrgexaDDXDriverInit(ScreenPtr pScreen)
52805b261ecSmrg{
52905b261ecSmrg    ExaScreenPriv(pScreen);
53005b261ecSmrg
53105b261ecSmrg    pExaScr->migration = ExaMigrationSmart;
53205b261ecSmrg    pExaScr->checkDirtyCorrectness = TRUE;
53305b261ecSmrg}
534