1f502a9faSjoerg/* $NetBSD: ffb_exa.c,v 1.5 2016/09/27 19:12:53 joerg Exp $ */
289b0bd4cSmacallan/*
389b0bd4cSmacallan * Copyright (c) 2015 Michael Lorenz
489b0bd4cSmacallan * All rights reserved.
589b0bd4cSmacallan *
689b0bd4cSmacallan * Redistribution and use in source and binary forms, with or without
789b0bd4cSmacallan * modification, are permitted provided that the following conditions
889b0bd4cSmacallan * are met:
989b0bd4cSmacallan *
1089b0bd4cSmacallan *    - Redistributions of source code must retain the above copyright
1189b0bd4cSmacallan *      notice, this list of conditions and the following disclaimer.
1289b0bd4cSmacallan *    - Redistributions in binary form must reproduce the above
1389b0bd4cSmacallan *      copyright notice, this list of conditions and the following
1489b0bd4cSmacallan *      disclaimer in the documentation and/or other materials provided
1589b0bd4cSmacallan *      with the distribution.
1689b0bd4cSmacallan *
1789b0bd4cSmacallan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1889b0bd4cSmacallan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1989b0bd4cSmacallan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2089b0bd4cSmacallan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2189b0bd4cSmacallan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2289b0bd4cSmacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2389b0bd4cSmacallan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2489b0bd4cSmacallan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2589b0bd4cSmacallan * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2689b0bd4cSmacallan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2789b0bd4cSmacallan * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2889b0bd4cSmacallan * POSSIBILITY OF SUCH DAMAGE.
2989b0bd4cSmacallan *
3089b0bd4cSmacallan */
3189b0bd4cSmacallan
3289b0bd4cSmacallan#include <sys/types.h>
3389b0bd4cSmacallan
34dda79b8eSmrg#ifdef HAVE_CONFIG_H
35dda79b8eSmrg#include "config.h"
36dda79b8eSmrg#endif
37dda79b8eSmrg
38f1295e53Smrg#include "ffb_fifo.h"
39f1295e53Smrg#include "ffb_rcache.h"
40f1295e53Smrg#include "ffb.h"
41f1295e53Smrg#include "ffb_regs.h"
42f1295e53Smrg
4389b0bd4cSmacallan/* all driver need this */
4489b0bd4cSmacallan#include "xf86.h"
4589b0bd4cSmacallan#include "xf86_OSproc.h"
4689b0bd4cSmacallan#include "compiler.h"
4789b0bd4cSmacallan#include "exa.h"
4889b0bd4cSmacallan
4989b0bd4cSmacallanextern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long);
5089b0bd4cSmacallanextern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long);
5189b0bd4cSmacallan
5289b0bd4cSmacallan/*#define FFB_DEBUG*/
5389b0bd4cSmacallan
5489b0bd4cSmacallan#ifdef FFB_DEBUG
5589b0bd4cSmacallan#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__);
5689b0bd4cSmacallan#define DPRINTF xf86Msg
5789b0bd4cSmacallan#else
5889b0bd4cSmacallan#define ENTER
5989b0bd4cSmacallan#define DPRINTF while (0) xf86Msg
6089b0bd4cSmacallan#endif
6189b0bd4cSmacallan
62504f16bcSmacallan#define arraysize(ary)        (sizeof(ary) / sizeof(ary[0]))
63504f16bcSmacallan
64504f16bcSmacallanint src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8,
65504f16bcSmacallan		     PICT_a8b8g8r8, PICT_x8b8g8r8, PICT_a8};
66504f16bcSmacallanint tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_a8};
67504f16bcSmacallan
6889b0bd4cSmacallanstatic void
6989b0bd4cSmacallanFFBWaitMarker(ScreenPtr pScreen, int Marker)
7089b0bd4cSmacallan{
7189b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
7289b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
7389b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
7489b0bd4cSmacallan
7589b0bd4cSmacallan	FFBWait(pFfb, ffb);
7689b0bd4cSmacallan}
7789b0bd4cSmacallan
7889b0bd4cSmacallanstatic Bool
7989b0bd4cSmacallanFFBPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
8089b0bd4cSmacallan		int xdir, int ydir, int alu, Pixel planemask)
8189b0bd4cSmacallan{
8289b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
8389b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
8489b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
8589b0bd4cSmacallan
8689b0bd4cSmacallan	ENTER;
8789b0bd4cSmacallan	pFfb->srcpitch = exaGetPixmapPitch(pSrcPixmap);
8889b0bd4cSmacallan	pFfb->srcoff = exaGetPixmapOffset(pSrcPixmap);
8989b0bd4cSmacallan	pFfb->xdir = xdir;
9089b0bd4cSmacallan	pFfb->ydir = ydir;
9189b0bd4cSmacallan	pFfb->rop = alu;
9289b0bd4cSmacallan	pFfb->planemask = planemask;
9389b0bd4cSmacallan	return TRUE;
9489b0bd4cSmacallan}
9589b0bd4cSmacallan
9689b0bd4cSmacallanstatic void
9789b0bd4cSmacallanFFBCopy(PixmapPtr pDstPixmap,
9889b0bd4cSmacallan         int srcX, int srcY, int dstX, int dstY, int w, int h)
9989b0bd4cSmacallan{
10089b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
10189b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
10289b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
10389b0bd4cSmacallan	unsigned char *src, *dst, *sfb32;
10489b0bd4cSmacallan	int psz_shift = 2;
10589b0bd4cSmacallan	int sdkind;
10689b0bd4cSmacallan
10789b0bd4cSmacallan	ENTER;
10889b0bd4cSmacallan	if ((srcX == dstX) && (srcY != dstY) && (pFfb->rop == GXcopy)) {
10989b0bd4cSmacallan		/* we can use the vscroll command */
11089b0bd4cSmacallan		FFB_ATTR_VSCROLL_XAA(pFfb, pFfb->planemask);
11189b0bd4cSmacallan		FFBFifo(pFfb, 7);
11289b0bd4cSmacallan		ffb->drawop = FFB_DRAWOP_VSCROLL;
11389b0bd4cSmacallan		FFB_WRITE64(&ffb->by, srcY, srcX);
11489b0bd4cSmacallan                       FFB_WRITE64_2(&ffb->dy, dstY, dstX);
11589b0bd4cSmacallan                       FFB_WRITE64_3(&ffb->bh, h, w);
11689b0bd4cSmacallan		exaMarkSync(pDstPixmap->drawable.pScreen);
11789b0bd4cSmacallan		return;
11889b0bd4cSmacallan	}
11989b0bd4cSmacallan	FFB_ATTR_SFB_VAR_XAA(pFfb, pFfb->planemask, pFfb->rop);
120504f16bcSmacallan	if (pFfb->use_blkread_prefetch) {
121504f16bcSmacallan		FFBFifo(pFfb, 1);
122504f16bcSmacallan		if (pFfb->xdir < 0)
123504f16bcSmacallan			ffb->mer = FFB_MER_EDRA;
124504f16bcSmacallan		else
125504f16bcSmacallan			ffb->mer = FFB_MER_EIRA;
126504f16bcSmacallan	}
12789b0bd4cSmacallan	FFBWait(pFfb, ffb);
12889b0bd4cSmacallan	sfb32 = (unsigned char *) pFfb->sfb32;
12989b0bd4cSmacallan	src = sfb32 + (srcY * (2048 << psz_shift)) + (srcX << psz_shift);
13089b0bd4cSmacallan	dst = sfb32 + (dstY * (2048 << psz_shift)) + (dstX << psz_shift);
13189b0bd4cSmacallan	sdkind = (2048 << psz_shift);
13289b0bd4cSmacallan
13389b0bd4cSmacallan	if (pFfb->ydir < 0) {
13489b0bd4cSmacallan		src += ((h - 1) * (2048 << psz_shift));
13589b0bd4cSmacallan		dst += ((h - 1) * (2048 << psz_shift));
13689b0bd4cSmacallan		sdkind = -sdkind;
13789b0bd4cSmacallan	}
13889b0bd4cSmacallan	w <<= psz_shift;
13989b0bd4cSmacallan	if (pFfb->xdir < 0)
14089b0bd4cSmacallan		VISmoveImageRL(src, dst, w, h, sdkind, sdkind);
14189b0bd4cSmacallan	else
14289b0bd4cSmacallan		VISmoveImageLR(src, dst, w, h, sdkind, sdkind);
143504f16bcSmacallan	if (pFfb->use_blkread_prefetch) {
144504f16bcSmacallan		FFBFifo(pFfb, 1);
145504f16bcSmacallan		ffb->mer = FFB_MER_DRA;
146504f16bcSmacallan	}
14789b0bd4cSmacallan}
14889b0bd4cSmacallan
14989b0bd4cSmacallanstatic void
15089b0bd4cSmacallanFFBDoneCopy(PixmapPtr pDstPixmap)
15189b0bd4cSmacallan{
15289b0bd4cSmacallan}
15389b0bd4cSmacallan
15489b0bd4cSmacallanstatic Bool
15589b0bd4cSmacallanFFBPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
15689b0bd4cSmacallan{
15789b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
15889b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
15989b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
16089b0bd4cSmacallan	unsigned int ppc, ppc_mask, fbc;
16189b0bd4cSmacallan
16289b0bd4cSmacallan	ENTER;
16389b0bd4cSmacallan	FFBWait(pFfb, ffb);
16489b0bd4cSmacallan	pFfb->planemask = planemask;
16589b0bd4cSmacallan	pFfb->rop = alu;
16689b0bd4cSmacallan
16789b0bd4cSmacallan	fbc = pFfb->fbc;
16889b0bd4cSmacallan	if (pFfb->ffb_res == ffb_res_high)
16989b0bd4cSmacallan		fbc |= FFB_FBC_WB_B;
17089b0bd4cSmacallan	ppc = FFB_PPC_ABE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID;
17189b0bd4cSmacallan	ppc_mask = FFB_PPC_ABE_MASK | FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK;
17289b0bd4cSmacallan
17389b0bd4cSmacallan	FFB_ATTR_RAW(pFfb, ppc, ppc_mask, planemask,
17489b0bd4cSmacallan                    (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8),
17589b0bd4cSmacallan                    FFB_DRAWOP_RECTANGLE, fg, fbc, pFfb->wid);
17689b0bd4cSmacallan
17789b0bd4cSmacallan	return TRUE;
17889b0bd4cSmacallan}
17989b0bd4cSmacallan
18089b0bd4cSmacallanstatic void
18189b0bd4cSmacallanFFBSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
18289b0bd4cSmacallan{
18389b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
18489b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
18589b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
18689b0bd4cSmacallan
18789b0bd4cSmacallan	ENTER;
18889b0bd4cSmacallan	FFBFifo(pFfb, 4);
18989b0bd4cSmacallan	FFB_WRITE64(&ffb->by, y1, x1);
19089b0bd4cSmacallan	FFB_WRITE64_2(&ffb->bh, y2 - y1, x2 - x1);
19189b0bd4cSmacallan	exaMarkSync(pPixmap->drawable.pScreen);
19289b0bd4cSmacallan}
19389b0bd4cSmacallan
19489b0bd4cSmacallanstatic Bool
19589b0bd4cSmacallanFFBUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h,
19689b0bd4cSmacallan    char *src, int src_pitch)
19789b0bd4cSmacallan{
19889b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
19989b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
20089b0bd4cSmacallan	unsigned char *dst, *sfb32;
20189b0bd4cSmacallan	int psz_shift = 2;
20289b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
20389b0bd4cSmacallan
20489b0bd4cSmacallan	ENTER;
20589b0bd4cSmacallan	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
20689b0bd4cSmacallan	FFBWait(pFfb, ffb);
20789b0bd4cSmacallan
20889b0bd4cSmacallan	sfb32 = (unsigned char *) pFfb->sfb32;
20989b0bd4cSmacallan	dst = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift);
21089b0bd4cSmacallan	VISmoveImageLR(src, dst, w << psz_shift, h,
21189b0bd4cSmacallan		src_pitch, (2048 << psz_shift));
21289b0bd4cSmacallan	return TRUE;
21389b0bd4cSmacallan}
21489b0bd4cSmacallan
21589b0bd4cSmacallanstatic Bool
21689b0bd4cSmacallanFFBDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
21789b0bd4cSmacallan    char *dst, int dst_pitch)
21889b0bd4cSmacallan{
21989b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
22089b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
22189b0bd4cSmacallan	unsigned char *src, *sfb32;
22289b0bd4cSmacallan	int psz_shift = 2;
22389b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
22489b0bd4cSmacallan
22589b0bd4cSmacallan	ENTER;
22689b0bd4cSmacallan	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
227504f16bcSmacallan	if (pFfb->use_blkread_prefetch) {
228504f16bcSmacallan		FFBFifo(pFfb, 1);
229504f16bcSmacallan		ffb->mer = FFB_MER_EIRA;
230504f16bcSmacallan	}
23189b0bd4cSmacallan	FFBWait(pFfb, ffb);
23289b0bd4cSmacallan
23389b0bd4cSmacallan	sfb32 = (unsigned char *) pFfb->sfb32;
23489b0bd4cSmacallan	src = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift);
23589b0bd4cSmacallan	VISmoveImageLR(src, dst, w << psz_shift, h,
23689b0bd4cSmacallan		(2048 << psz_shift), dst_pitch);
237504f16bcSmacallan	if (pFfb->use_blkread_prefetch) {
238504f16bcSmacallan		FFBFifo(pFfb, 1);
239504f16bcSmacallan		ffb->mer = FFB_MER_DRA;
240504f16bcSmacallan	}
24189b0bd4cSmacallan	return TRUE;
24289b0bd4cSmacallan}
24389b0bd4cSmacallan
244504f16bcSmacallanstatic Bool
24589b0bd4cSmacallanFFBCheckComposite(int op, PicturePtr pSrcPicture,
24689b0bd4cSmacallan                           PicturePtr pMaskPicture,
24789b0bd4cSmacallan                           PicturePtr pDstPicture)
24889b0bd4cSmacallan{
249504f16bcSmacallan	int i, ok = FALSE;
250504f16bcSmacallan
251504f16bcSmacallan	ENTER;
252504f16bcSmacallan
253504f16bcSmacallan	i = 0;
254504f16bcSmacallan	while ((i < arraysize(src_formats)) && (!ok)) {
255504f16bcSmacallan		ok =  (pSrcPicture->format == src_formats[i]);
256504f16bcSmacallan		i++;
257504f16bcSmacallan	}
258504f16bcSmacallan
259504f16bcSmacallan	if (!ok) {
260504f16bcSmacallan		xf86Msg(X_ERROR, "%s: unsupported src format %x\n",
261504f16bcSmacallan		    __func__, pSrcPicture->format);
262504f16bcSmacallan		return FALSE;
263504f16bcSmacallan	}
264504f16bcSmacallan
265504f16bcSmacallan	DPRINTF(X_ERROR, "src is %x, %d: %d %d\n", pSrcPicture->format, op,
266504f16bcSmacallan	    pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height);
267504f16bcSmacallan
268504f16bcSmacallan	if (pMaskPicture != NULL) {
269504f16bcSmacallan		DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format,
270504f16bcSmacallan		    pMaskPicture->pDrawable->width,
271504f16bcSmacallan		    pMaskPicture->pDrawable->height);
272504f16bcSmacallan	}
273504f16bcSmacallan	return TRUE;
27489b0bd4cSmacallan}
27589b0bd4cSmacallan
276504f16bcSmacallanstatic Bool
27789b0bd4cSmacallanFFBPrepareComposite(int op, PicturePtr pSrcPicture,
27889b0bd4cSmacallan                             PicturePtr pMaskPicture,
27989b0bd4cSmacallan                             PicturePtr pDstPicture,
28089b0bd4cSmacallan                             PixmapPtr  pSrc,
28189b0bd4cSmacallan                             PixmapPtr  pMask,
28289b0bd4cSmacallan                             PixmapPtr  pDst)
28389b0bd4cSmacallan{
28489b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
28589b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
28689b0bd4cSmacallan
28789b0bd4cSmacallan	ENTER;
288504f16bcSmacallan
289504f16bcSmacallan	pFfb->no_source_pixmap = FALSE;
290504f16bcSmacallan	pFfb->source_is_solid = FALSE;
291504f16bcSmacallan
292504f16bcSmacallan	if (pSrcPicture->format == PICT_a1) {
293504f16bcSmacallan		xf86Msg(X_ERROR, "src mono, dst %x, op %d\n",
294504f16bcSmacallan		    pDstPicture->format, op);
295504f16bcSmacallan		if (pMaskPicture != NULL) {
296504f16bcSmacallan			xf86Msg(X_ERROR, "msk %x\n", pMaskPicture->format);
297504f16bcSmacallan		}
298504f16bcSmacallan	}
299504f16bcSmacallan	if (pSrcPicture->pSourcePict != NULL) {
300504f16bcSmacallan		if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
301504f16bcSmacallan			pFfb->fillcolour =
302504f16bcSmacallan			    pSrcPicture->pSourcePict->solidFill.color;
303f502a9faSjoerg			DPRINTF(X_ERROR, "%s: solid src %08"PRIx32"\n",
304f502a9faSjoerg			    __func__, (uint32_t)pFfb->fillcolour);
305504f16bcSmacallan			pFfb->no_source_pixmap = TRUE;
306504f16bcSmacallan			pFfb->source_is_solid = TRUE;
307504f16bcSmacallan		}
308504f16bcSmacallan	}
309504f16bcSmacallan	if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) {
310504f16bcSmacallan		if (pMaskPicture->pSourcePict->type ==
311504f16bcSmacallan		    SourcePictTypeSolidFill) {
312504f16bcSmacallan			pFfb->fillcolour =
313504f16bcSmacallan			   pMaskPicture->pSourcePict->solidFill.color;
314f502a9faSjoerg			xf86Msg(X_ERROR, "%s: solid mask %08"PRIx32"\n",
315f502a9faSjoerg			    __func__, (uint32_t)pFfb->fillcolour);
316504f16bcSmacallan		}
317504f16bcSmacallan	}
318504f16bcSmacallan	if (pMaskPicture != NULL) {
319504f16bcSmacallan		pFfb->mskoff = exaGetPixmapOffset(pMask);
320504f16bcSmacallan		pFfb->mskpitch = exaGetPixmapPitch(pMask);
321504f16bcSmacallan		pFfb->mskformat = pMaskPicture->format;
322504f16bcSmacallan	} else {
323504f16bcSmacallan		pFfb->mskoff = 0;
324504f16bcSmacallan		pFfb->mskpitch = 0;
325504f16bcSmacallan		pFfb->mskformat = 0;
326504f16bcSmacallan	}
327504f16bcSmacallan	if (pSrc != NULL) {
328504f16bcSmacallan		pFfb->source_is_solid =
329504f16bcSmacallan		   ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1));
330504f16bcSmacallan		pFfb->srcoff = exaGetPixmapOffset(pSrc);
331504f16bcSmacallan		pFfb->srcpitch = exaGetPixmapPitch(pSrc);
332504f16bcSmacallan		if (pFfb->source_is_solid) {
333504f16bcSmacallan			pFfb->fillcolour = *(uint32_t *)(pFfb->fb + pFfb->srcoff);
334504f16bcSmacallan		}
335504f16bcSmacallan	}
336504f16bcSmacallan	pFfb->srcformat = pSrcPicture->format;
337504f16bcSmacallan	pFfb->dstformat = pDstPicture->format;
338504f16bcSmacallan
339504f16bcSmacallan	if (pFfb->source_is_solid) {
340504f16bcSmacallan		uint32_t temp;
341504f16bcSmacallan
342504f16bcSmacallan		/* swap solid source as needed */
343504f16bcSmacallan		switch (pFfb->srcformat) {
344504f16bcSmacallan			case PICT_a8r8g8b8:
345504f16bcSmacallan			case PICT_x8r8g8b8:
346504f16bcSmacallan				temp = (pFfb->fillcolour & 0x000000ff) << 16;
347504f16bcSmacallan				temp |= (pFfb->fillcolour & 0x00ff0000) >> 16;
348504f16bcSmacallan				temp |= (pFfb->fillcolour & 0xff00ff00);
349504f16bcSmacallan				pFfb->fillcolour = temp;
350504f16bcSmacallan				break;
351504f16bcSmacallan		}
352504f16bcSmacallan	}
353504f16bcSmacallan	pFfb->op = op;
354504f16bcSmacallan	return TRUE;
35589b0bd4cSmacallan}
35689b0bd4cSmacallan
357504f16bcSmacallanstatic void
35889b0bd4cSmacallanFFBComposite(PixmapPtr pDst, int srcX, int srcY,
35989b0bd4cSmacallan                              int maskX, int maskY,
36089b0bd4cSmacallan                              int dstX, int dstY,
36189b0bd4cSmacallan                              int width, int height)
36289b0bd4cSmacallan{
36389b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
36489b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
36589b0bd4cSmacallan	exaMarkSync(pDst->drawable.pScreen);
36689b0bd4cSmacallan}
36789b0bd4cSmacallan
36889b0bd4cSmacallanstatic Bool
36989b0bd4cSmacallanFFBPrepareAccess(PixmapPtr pPix, int index)
37089b0bd4cSmacallan{
37189b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
37289b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
37389b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
37489b0bd4cSmacallan
37589b0bd4cSmacallan	ENTER;
37689b0bd4cSmacallan	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
37789b0bd4cSmacallan	FFBWait(pFfb, ffb);
37889b0bd4cSmacallan
37989b0bd4cSmacallan	return TRUE;
38089b0bd4cSmacallan}
38189b0bd4cSmacallan
38289b0bd4cSmacallanstatic void
38389b0bd4cSmacallanFFBFinishAccess(PixmapPtr pPix, int index)
38489b0bd4cSmacallan{
38589b0bd4cSmacallan}
38689b0bd4cSmacallan
38789b0bd4cSmacallanBool
38889b0bd4cSmacallanFFBInitEXA(ScreenPtr pScreen)
38989b0bd4cSmacallan{
39089b0bd4cSmacallan	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
39189b0bd4cSmacallan	FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn);
39289b0bd4cSmacallan	ffb_fbcPtr ffb = pFfb->regs;
39389b0bd4cSmacallan	ExaDriverPtr pExa;
39489b0bd4cSmacallan
39589b0bd4cSmacallan	pFfb->fbc = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A |
39689b0bd4cSmacallan			 FFB_FBC_WE_FORCEON |
39789b0bd4cSmacallan			 FFB_FBC_SB_BOTH |
39889b0bd4cSmacallan			 FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF |
39989b0bd4cSmacallan			 FFB_FBC_RGBE_MASK |
40089b0bd4cSmacallan			 FFB_FBC_XE_ON);
40189b0bd4cSmacallan	pFfb->wid = FFBWidAlloc(pFfb, TrueColor, 0, TRUE);
40289b0bd4cSmacallan	if (pFfb->wid == (unsigned int) -1)
40389b0bd4cSmacallan		return FALSE;
40489b0bd4cSmacallan
40589b0bd4cSmacallan	pFfb->ppc_cache = (FFB_PPC_FW_DISABLE |
40689b0bd4cSmacallan			   FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST |
40789b0bd4cSmacallan			   FFB_PPC_XS_WID | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST |
40889b0bd4cSmacallan			   FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE);
40989b0bd4cSmacallan	pFfb->wid_cache = pFfb->wid;
41089b0bd4cSmacallan	pFfb->pmask_cache = ~0;
41189b0bd4cSmacallan	pFfb->rop_cache = (FFB_ROP_NEW | (FFB_ROP_NEW << 8));
41289b0bd4cSmacallan	pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE;
41389b0bd4cSmacallan	pFfb->fg_cache = pFfb->bg_cache = 0;
41489b0bd4cSmacallan	pFfb->fontw_cache = 32;
41589b0bd4cSmacallan	pFfb->fontinc_cache = (1 << 16) | 0;
41689b0bd4cSmacallan	pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A |
41789b0bd4cSmacallan			   FFB_FBC_WE_FORCEON |
41889b0bd4cSmacallan			   FFB_FBC_SB_BOTH |
41989b0bd4cSmacallan			   FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF |
42089b0bd4cSmacallan			   FFB_FBC_RGBE_OFF |
42189b0bd4cSmacallan			   FFB_FBC_XE_ON);
42289b0bd4cSmacallan
42389b0bd4cSmacallan	/* We will now clear the screen: we'll draw a rectangle covering all the
42489b0bd4cSmacallan	 * viewscreen, using a 'blackness' ROP.
42589b0bd4cSmacallan	 */
42689b0bd4cSmacallan	FFBFifo(pFfb, 22);
42789b0bd4cSmacallan	ffb->fbc = pFfb->fbc_cache;
42889b0bd4cSmacallan	ffb->ppc = pFfb->ppc_cache;
42989b0bd4cSmacallan	ffb->wid = pFfb->wid_cache;
43089b0bd4cSmacallan	ffb->xpmask = 0xff;
43189b0bd4cSmacallan	ffb->pmask = pFfb->pmask_cache;
43289b0bd4cSmacallan	ffb->rop = pFfb->rop_cache;
43389b0bd4cSmacallan	ffb->drawop = pFfb->drawop_cache;
43489b0bd4cSmacallan	ffb->fg = pFfb->fg_cache;
43589b0bd4cSmacallan	ffb->bg = pFfb->bg_cache;
43689b0bd4cSmacallan	ffb->fontw = pFfb->fontw_cache;
43789b0bd4cSmacallan	ffb->fontinc = pFfb->fontinc_cache;
43889b0bd4cSmacallan	ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
43989b0bd4cSmacallan	ffb->cmp = 0x80808080;
44089b0bd4cSmacallan	ffb->matchab = 0x80808080;
44189b0bd4cSmacallan	ffb->magnab = 0x80808080;
44289b0bd4cSmacallan	ffb->blendc = (FFB_BLENDC_FORCE_ONE |
44389b0bd4cSmacallan		       FFB_BLENDC_DF_ONE_M_A |
44489b0bd4cSmacallan		       FFB_BLENDC_SF_A);
44589b0bd4cSmacallan	ffb->blendc1 = 0;
44689b0bd4cSmacallan	ffb->blendc2 = 0;
44789b0bd4cSmacallan	FFB_WRITE64(&ffb->by, 0, 0);
44889b0bd4cSmacallan	FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width);
44989b0bd4cSmacallan	FFBWait(pFfb, ffb);
45089b0bd4cSmacallan
45189b0bd4cSmacallan	FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy);
45289b0bd4cSmacallan	FFBWait(pFfb, ffb);
45389b0bd4cSmacallan
454504f16bcSmacallan	FFB_HardwareSetup(pFfb);
45589b0bd4cSmacallan	pExa = exaDriverAlloc();
45689b0bd4cSmacallan	if (!pExa)
45789b0bd4cSmacallan		return FALSE;
45889b0bd4cSmacallan
45989b0bd4cSmacallan	pFfb->pExa = pExa;
46089b0bd4cSmacallan
46189b0bd4cSmacallan	pExa->exa_major = EXA_VERSION_MAJOR;
46289b0bd4cSmacallan	pExa->exa_minor = EXA_VERSION_MINOR;
46389b0bd4cSmacallan
46489b0bd4cSmacallan
46589b0bd4cSmacallan	pExa->memoryBase = (char *)pFfb->sfb32;
46689b0bd4cSmacallan	/*
46789b0bd4cSmacallan	 * we don't have usable off-screen memory but EXA craps out if we don't
46889b0bd4cSmacallan	 * pretend that we do, so register a ridiculously small amount and
46989b0bd4cSmacallan	 * cross fingers
47089b0bd4cSmacallan	 */
47189b0bd4cSmacallan	pExa->memorySize = 8192 * pFfb->psdp->height + 4;
47289b0bd4cSmacallan	pExa->offScreenBase = pExa->memorySize - 4;
47389b0bd4cSmacallan
47489b0bd4cSmacallan	/* we want to use 64bit aligned accesses */
47589b0bd4cSmacallan	pExa->pixmapOffsetAlign = 8;
47689b0bd4cSmacallan	pExa->pixmapPitchAlign = 8;
47789b0bd4cSmacallan
47889b0bd4cSmacallan	pExa->flags = EXA_OFFSCREEN_PIXMAPS |
47989b0bd4cSmacallan		      /*EXA_SUPPORTS_OFFSCREEN_OVERLAPS |*/
48089b0bd4cSmacallan		      EXA_MIXED_PIXMAPS;
48189b0bd4cSmacallan
48289b0bd4cSmacallan	pExa->maxX = 2048;
48389b0bd4cSmacallan	pExa->maxY = 2048;
48489b0bd4cSmacallan
48589b0bd4cSmacallan	pExa->WaitMarker = FFBWaitMarker;
48689b0bd4cSmacallan
48789b0bd4cSmacallan	pExa->PrepareSolid = FFBPrepareSolid;
48889b0bd4cSmacallan	pExa->Solid = FFBSolid;
48989b0bd4cSmacallan	pExa->DoneSolid = FFBDoneCopy;
490504f16bcSmacallan
49189b0bd4cSmacallan	pExa->PrepareCopy = FFBPrepareCopy;
49289b0bd4cSmacallan	pExa->Copy = FFBCopy;
49389b0bd4cSmacallan	pExa->DoneCopy = FFBDoneCopy;
494504f16bcSmacallan
49589b0bd4cSmacallan	pExa->UploadToScreen = FFBUploadToScreen;
49689b0bd4cSmacallan	pExa->DownloadFromScreen = FFBDownloadFromScreen;
497504f16bcSmacallan
49889b0bd4cSmacallan	pExa->PrepareAccess = FFBPrepareAccess;
49989b0bd4cSmacallan	pExa->FinishAccess = FFBFinishAccess;
50089b0bd4cSmacallan
501504f16bcSmacallanif(0) {
502504f16bcSmacallan	pExa->CheckComposite = FFBCheckComposite;
503504f16bcSmacallan	pExa->PrepareComposite = FFBPrepareComposite;
504504f16bcSmacallan	pExa->Composite = FFBComposite;
505504f16bcSmacallan	pExa->DoneComposite = FFBDoneCopy;
506504f16bcSmacallan}
50789b0bd4cSmacallan	return exaDriverInit(pScreen, pExa);
50889b0bd4cSmacallan}
509