/* $NetBSD: ffb_exa.c,v 1.5 2016/09/27 19:12:53 joerg Exp $ */ /* * Copyright (c) 2015 Michael Lorenz * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "ffb_fifo.h" #include "ffb_rcache.h" #include "ffb.h" #include "ffb_regs.h" /* all driver need this */ #include "xf86.h" #include "xf86_OSproc.h" #include "compiler.h" #include "exa.h" extern void VISmoveImageRL(unsigned char *, unsigned char *, long, long, long, long); extern void VISmoveImageLR(unsigned char *, unsigned char *, long, long, long, long); /*#define FFB_DEBUG*/ #ifdef FFB_DEBUG #define ENTER xf86Msg(X_ERROR, "%s>\n", __func__); #define DPRINTF xf86Msg #else #define ENTER #define DPRINTF while (0) xf86Msg #endif #define arraysize(ary) (sizeof(ary) / sizeof(ary[0])) int src_formats[] = {PICT_a8r8g8b8, PICT_x8r8g8b8, PICT_a8b8g8r8, PICT_x8b8g8r8, PICT_a8}; int tex_formats[] = {PICT_a8r8g8b8, PICT_a8b8g8r8, PICT_a8}; static void FFBWaitMarker(ScreenPtr pScreen, int Marker) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; FFBWait(pFfb, ffb); } static Bool FFBPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; ENTER; pFfb->srcpitch = exaGetPixmapPitch(pSrcPixmap); pFfb->srcoff = exaGetPixmapOffset(pSrcPixmap); pFfb->xdir = xdir; pFfb->ydir = ydir; pFfb->rop = alu; pFfb->planemask = planemask; return TRUE; } static void FFBCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int w, int h) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; unsigned char *src, *dst, *sfb32; int psz_shift = 2; int sdkind; ENTER; if ((srcX == dstX) && (srcY != dstY) && (pFfb->rop == GXcopy)) { /* we can use the vscroll command */ FFB_ATTR_VSCROLL_XAA(pFfb, pFfb->planemask); FFBFifo(pFfb, 7); ffb->drawop = FFB_DRAWOP_VSCROLL; FFB_WRITE64(&ffb->by, srcY, srcX); FFB_WRITE64_2(&ffb->dy, dstY, dstX); FFB_WRITE64_3(&ffb->bh, h, w); exaMarkSync(pDstPixmap->drawable.pScreen); return; } FFB_ATTR_SFB_VAR_XAA(pFfb, pFfb->planemask, pFfb->rop); if (pFfb->use_blkread_prefetch) { FFBFifo(pFfb, 1); if (pFfb->xdir < 0) ffb->mer = FFB_MER_EDRA; else ffb->mer = FFB_MER_EIRA; } FFBWait(pFfb, ffb); sfb32 = (unsigned char *) pFfb->sfb32; src = sfb32 + (srcY * (2048 << psz_shift)) + (srcX << psz_shift); dst = sfb32 + (dstY * (2048 << psz_shift)) + (dstX << psz_shift); sdkind = (2048 << psz_shift); if (pFfb->ydir < 0) { src += ((h - 1) * (2048 << psz_shift)); dst += ((h - 1) * (2048 << psz_shift)); sdkind = -sdkind; } w <<= psz_shift; if (pFfb->xdir < 0) VISmoveImageRL(src, dst, w, h, sdkind, sdkind); else VISmoveImageLR(src, dst, w, h, sdkind, sdkind); if (pFfb->use_blkread_prefetch) { FFBFifo(pFfb, 1); ffb->mer = FFB_MER_DRA; } } static void FFBDoneCopy(PixmapPtr pDstPixmap) { } static Bool FFBPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; unsigned int ppc, ppc_mask, fbc; ENTER; FFBWait(pFfb, ffb); pFfb->planemask = planemask; pFfb->rop = alu; fbc = pFfb->fbc; if (pFfb->ffb_res == ffb_res_high) fbc |= FFB_FBC_WB_B; ppc = FFB_PPC_ABE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID; ppc_mask = FFB_PPC_ABE_MASK | FFB_PPC_APE_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK; FFB_ATTR_RAW(pFfb, ppc, ppc_mask, planemask, (FFB_ROP_EDIT_BIT | alu) | (FFB_ROP_NEW << 8), FFB_DRAWOP_RECTANGLE, fg, fbc, pFfb->wid); return TRUE; } static void FFBSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; ENTER; FFBFifo(pFfb, 4); FFB_WRITE64(&ffb->by, y1, x1); FFB_WRITE64_2(&ffb->bh, y2 - y1, x2 - x1); exaMarkSync(pPixmap->drawable.pScreen); } static Bool FFBUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) { ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); unsigned char *dst, *sfb32; int psz_shift = 2; ffb_fbcPtr ffb = pFfb->regs; ENTER; FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); FFBWait(pFfb, ffb); sfb32 = (unsigned char *) pFfb->sfb32; dst = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift); VISmoveImageLR(src, dst, w << psz_shift, h, src_pitch, (2048 << psz_shift)); return TRUE; } static Bool FFBDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); unsigned char *src, *sfb32; int psz_shift = 2; ffb_fbcPtr ffb = pFfb->regs; ENTER; FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); if (pFfb->use_blkread_prefetch) { FFBFifo(pFfb, 1); ffb->mer = FFB_MER_EIRA; } FFBWait(pFfb, ffb); sfb32 = (unsigned char *) pFfb->sfb32; src = sfb32 + (y * (2048 << psz_shift)) + (x << psz_shift); VISmoveImageLR(src, dst, w << psz_shift, h, (2048 << psz_shift), dst_pitch); if (pFfb->use_blkread_prefetch) { FFBFifo(pFfb, 1); ffb->mer = FFB_MER_DRA; } return TRUE; } static Bool FFBCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) { int i, ok = FALSE; ENTER; i = 0; while ((i < arraysize(src_formats)) && (!ok)) { ok = (pSrcPicture->format == src_formats[i]); i++; } if (!ok) { xf86Msg(X_ERROR, "%s: unsupported src format %x\n", __func__, pSrcPicture->format); return FALSE; } DPRINTF(X_ERROR, "src is %x, %d: %d %d\n", pSrcPicture->format, op, pSrcPicture->pDrawable->width, pSrcPicture->pDrawable->height); if (pMaskPicture != NULL) { DPRINTF(X_ERROR, "mask is %x %d %d\n", pMaskPicture->format, pMaskPicture->pDrawable->width, pMaskPicture->pDrawable->height); } return TRUE; } static Bool FFBPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) { ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ENTER; pFfb->no_source_pixmap = FALSE; pFfb->source_is_solid = FALSE; if (pSrcPicture->format == PICT_a1) { xf86Msg(X_ERROR, "src mono, dst %x, op %d\n", pDstPicture->format, op); if (pMaskPicture != NULL) { xf86Msg(X_ERROR, "msk %x\n", pMaskPicture->format); } } if (pSrcPicture->pSourcePict != NULL) { if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) { pFfb->fillcolour = pSrcPicture->pSourcePict->solidFill.color; DPRINTF(X_ERROR, "%s: solid src %08"PRIx32"\n", __func__, (uint32_t)pFfb->fillcolour); pFfb->no_source_pixmap = TRUE; pFfb->source_is_solid = TRUE; } } if ((pMaskPicture != NULL) && (pMaskPicture->pSourcePict != NULL)) { if (pMaskPicture->pSourcePict->type == SourcePictTypeSolidFill) { pFfb->fillcolour = pMaskPicture->pSourcePict->solidFill.color; xf86Msg(X_ERROR, "%s: solid mask %08"PRIx32"\n", __func__, (uint32_t)pFfb->fillcolour); } } if (pMaskPicture != NULL) { pFfb->mskoff = exaGetPixmapOffset(pMask); pFfb->mskpitch = exaGetPixmapPitch(pMask); pFfb->mskformat = pMaskPicture->format; } else { pFfb->mskoff = 0; pFfb->mskpitch = 0; pFfb->mskformat = 0; } if (pSrc != NULL) { pFfb->source_is_solid = ((pSrc->drawable.width == 1) && (pSrc->drawable.height == 1)); pFfb->srcoff = exaGetPixmapOffset(pSrc); pFfb->srcpitch = exaGetPixmapPitch(pSrc); if (pFfb->source_is_solid) { pFfb->fillcolour = *(uint32_t *)(pFfb->fb + pFfb->srcoff); } } pFfb->srcformat = pSrcPicture->format; pFfb->dstformat = pDstPicture->format; if (pFfb->source_is_solid) { uint32_t temp; /* swap solid source as needed */ switch (pFfb->srcformat) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: temp = (pFfb->fillcolour & 0x000000ff) << 16; temp |= (pFfb->fillcolour & 0x00ff0000) >> 16; temp |= (pFfb->fillcolour & 0xff00ff00); pFfb->fillcolour = temp; break; } } pFfb->op = op; return TRUE; } static void FFBComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); exaMarkSync(pDst->drawable.pScreen); } static Bool FFBPrepareAccess(PixmapPtr pPix, int index) { ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; ENTER; FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); FFBWait(pFfb, ffb); return TRUE; } static void FFBFinishAccess(PixmapPtr pPix, int index) { } Bool FFBInitEXA(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; FFBPtr pFfb = GET_FFB_FROM_SCRN(pScrn); ffb_fbcPtr ffb = pFfb->regs; ExaDriverPtr pExa; pFfb->fbc = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | FFB_FBC_WE_FORCEON | FFB_FBC_SB_BOTH | FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_MASK | FFB_FBC_XE_ON); pFfb->wid = FFBWidAlloc(pFfb, TrueColor, 0, TRUE); if (pFfb->wid == (unsigned int) -1) return FALSE; pFfb->ppc_cache = (FFB_PPC_FW_DISABLE | FFB_PPC_VCE_DISABLE | FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST | FFB_PPC_XS_WID | FFB_PPC_YS_CONST | FFB_PPC_ZS_CONST | FFB_PPC_DCE_DISABLE | FFB_PPC_ABE_DISABLE | FFB_PPC_TBE_OPAQUE); pFfb->wid_cache = pFfb->wid; pFfb->pmask_cache = ~0; pFfb->rop_cache = (FFB_ROP_NEW | (FFB_ROP_NEW << 8)); pFfb->drawop_cache = FFB_DRAWOP_RECTANGLE; pFfb->fg_cache = pFfb->bg_cache = 0; pFfb->fontw_cache = 32; pFfb->fontinc_cache = (1 << 16) | 0; pFfb->fbc_cache = (FFB_FBC_WB_A | FFB_FBC_WM_COMBINED | FFB_FBC_RB_A | FFB_FBC_WE_FORCEON | FFB_FBC_SB_BOTH | FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF | FFB_FBC_RGBE_OFF | FFB_FBC_XE_ON); /* We will now clear the screen: we'll draw a rectangle covering all the * viewscreen, using a 'blackness' ROP. */ FFBFifo(pFfb, 22); ffb->fbc = pFfb->fbc_cache; ffb->ppc = pFfb->ppc_cache; ffb->wid = pFfb->wid_cache; ffb->xpmask = 0xff; ffb->pmask = pFfb->pmask_cache; ffb->rop = pFfb->rop_cache; ffb->drawop = pFfb->drawop_cache; ffb->fg = pFfb->fg_cache; ffb->bg = pFfb->bg_cache; ffb->fontw = pFfb->fontw_cache; ffb->fontinc = pFfb->fontinc_cache; ffb->xclip = FFB_XCLIP_TEST_ALWAYS; ffb->cmp = 0x80808080; ffb->matchab = 0x80808080; ffb->magnab = 0x80808080; ffb->blendc = (FFB_BLENDC_FORCE_ONE | FFB_BLENDC_DF_ONE_M_A | FFB_BLENDC_SF_A); ffb->blendc1 = 0; ffb->blendc2 = 0; FFB_WRITE64(&ffb->by, 0, 0); FFB_WRITE64_2(&ffb->bh, pFfb->psdp->height, pFfb->psdp->width); FFBWait(pFfb, ffb); FFB_ATTR_SFB_VAR_XAA(pFfb, 0xffffffff, GXcopy); FFBWait(pFfb, ffb); FFB_HardwareSetup(pFfb); pExa = exaDriverAlloc(); if (!pExa) return FALSE; pFfb->pExa = pExa; pExa->exa_major = EXA_VERSION_MAJOR; pExa->exa_minor = EXA_VERSION_MINOR; pExa->memoryBase = (char *)pFfb->sfb32; /* * we don't have usable off-screen memory but EXA craps out if we don't * pretend that we do, so register a ridiculously small amount and * cross fingers */ pExa->memorySize = 8192 * pFfb->psdp->height + 4; pExa->offScreenBase = pExa->memorySize - 4; /* we want to use 64bit aligned accesses */ pExa->pixmapOffsetAlign = 8; pExa->pixmapPitchAlign = 8; pExa->flags = EXA_OFFSCREEN_PIXMAPS | /*EXA_SUPPORTS_OFFSCREEN_OVERLAPS |*/ EXA_MIXED_PIXMAPS; pExa->maxX = 2048; pExa->maxY = 2048; pExa->WaitMarker = FFBWaitMarker; pExa->PrepareSolid = FFBPrepareSolid; pExa->Solid = FFBSolid; pExa->DoneSolid = FFBDoneCopy; pExa->PrepareCopy = FFBPrepareCopy; pExa->Copy = FFBCopy; pExa->DoneCopy = FFBDoneCopy; pExa->UploadToScreen = FFBUploadToScreen; pExa->DownloadFromScreen = FFBDownloadFromScreen; pExa->PrepareAccess = FFBPrepareAccess; pExa->FinishAccess = FFBFinishAccess; if(0) { pExa->CheckComposite = FFBCheckComposite; pExa->PrepareComposite = FFBPrepareComposite; pExa->Composite = FFBComposite; pExa->DoneComposite = FFBDoneCopy; } return exaDriverInit(pScreen, pExa); }