/* * Sun GX and Turbo GX EXA support * * Copyright (C) 2015 Michael Lorenz * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/suncg6/cg6_exa.c $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "cg6.h" #include "cg6_regs.h" static CARD32 Cg6BlitROP[] = { ROP_BLIT(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_BLIT(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_BLIT(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_BLIT(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_BLIT(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; static CARD32 Cg6DrawROP[] = { ROP_FILL(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_FILL(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_FILL(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_FILL(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_FILL(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_FILL(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_FILL(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_FILL(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_FILL(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; #define runDraw(pCg6) { volatile CARD32 rubbish = pCg6->fbc->draw; } #define runBlit(pCg6) { volatile CARD32 rubbish = pCg6->fbc->blit; } /* * XXX * was GX_FULL, which apparently isn't enough on some (slower) CG6 like * the one found on the SPARCstation LX mainboard */ #define waitReady(pCg6) while(pCg6->fbc->s & GX_INPROGRESS) void Cg6InitEngine(Cg6Ptr); static void Cg6WaitMarker(ScreenPtr pScreen, int Marker) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Cg6Ptr p = GET_CG6_FROM_SCRN(pScrn); waitReady(p); } static Bool Cg6PrepareCopy ( PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask ) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); waitReady(pCg6); pCg6->fbc->mode = GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0; /* we probably don't need the following three */ pCg6->fbc->fg = 0xff; pCg6->fbc->bg = 0x00; pCg6->fbc->s = 0; pCg6->srcoff = exaGetPixmapOffset(pSrcPixmap) / pCg6->width; pCg6->fbc->alu = Cg6BlitROP[alu]; pCg6->fbc->pm = planemask; return TRUE; } static void Cg6Copy ( PixmapPtr pDstPixmap, int xSrc, int ySrc, int xDst, int yDst, int w, int h ) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); int doff; doff = exaGetPixmapOffset(pDstPixmap) / pCg6->width; waitReady(pCg6); pCg6->fbc->x0 = xSrc; pCg6->fbc->y0 = ySrc + pCg6->srcoff; pCg6->fbc->x1 = xSrc + w - 1; pCg6->fbc->y1 = ySrc + pCg6->srcoff + h - 1; pCg6->fbc->x2 = xDst; pCg6->fbc->y2 = yDst + doff; pCg6->fbc->x3 = xDst + w - 1; pCg6->fbc->y3 = yDst + doff + h - 1; runBlit(pCg6); exaMarkSync(pDstPixmap->drawable.pScreen); } static void Cg6DoneCopy(PixmapPtr pDstPixmap) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); waitReady(pCg6); } static Bool Cg6PrepareSolid( PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); CARD32 c2; pCg6->srcoff = exaGetPixmapOffset(pPixmap) / pCg6->width; waitReady(pCg6); pCg6->fbc->mode = GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0; pCg6->fbc->fg = fg; pCg6->fbc->s = 0; pCg6->fbc->alu = Cg6DrawROP[alu]; pCg6->fbc->pm = planemask; return TRUE; } static void Cg6Solid( PixmapPtr pPixmap, int x, int y, int x2, int y2) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); waitReady(pCg6); pCg6->fbc->arecty = y + pCg6->srcoff; pCg6->fbc->arectx = x; pCg6->fbc->rrecty = y2 - y - 1; pCg6->fbc->rrectx = x2 - x - 1; runDraw(pCg6); exaMarkSync(pPixmap->drawable.pScreen); } /* * UTS using host blits */ static Bool Cg6UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) { ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); uint32_t *sline; int dst_pitch = exaGetPixmapPitch(pDst); int dst_line = y + exaGetPixmapOffset(pDst) / pCg6->width; int i, bits; int words = (w + 3) >> 2; /* clip to the destination */ pCg6->fbc->clipmaxx = x + w - 1; pCg6->fbc->clipminx = x; /* see if the source is aligned, if not adjust */ bits = ((long)src) & 3; if (bits != 0) { src -= bits; w += bits; words = (w + 3) >> 2; x -= bits; } /* we assume that source pitch is always a multiple of 4 */ if ((src_pitch & 3) != 0) xf86Msg(X_ERROR, "pitch %d\n", src_pitch); waitReady(pCg6); pCg6->fbc->mode = GX_BLIT_NOSRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0; pCg6->fbc->alu = Cg6BlitROP[GXcopy]; pCg6->fbc->pm = 0xffffffff; pCg6->fbc->incx = 4; pCg6->fbc->incy = 0; while (h--) { pCg6->fbc->x0 = x; pCg6->fbc->x1 = x + 3; pCg6->fbc->y0 = dst_line; sline = (uint32_t *)src; for (i = 0; i < words; i++) { pCg6->fbc->font = *sline; sline++; } src += src_pitch; dst_line++; } pCg6->fbc->clipmaxx = 4096; pCg6->fbc->clipminx = 0; exaMarkSync(pDst->drawable.pScreen); return TRUE; } /* * Memcpy-based DFS. */ static Bool Cg6DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); uint8_t *src = pCg6->fb + exaGetPixmapOffset(pSrc); int src_pitch = exaGetPixmapPitch(pSrc); src += x + (y * src_pitch); while (h > 0) { memcpy(dst, src, w); src += src_pitch; dst += dst_pitch; h--; } return TRUE; } int CG6EXAInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); ExaDriverPtr pExa; Cg6InitEngine(pCg6); pExa = exaDriverAlloc(); if (!pExa) return FALSE; pCg6->pExa = pExa; pExa->exa_major = EXA_VERSION_MAJOR; pExa->exa_minor = EXA_VERSION_MINOR; pExa->memoryBase = pCg6->fb; /* round to multiple of pixmap pitch */ pExa->memorySize = (pCg6->vidmem / pCg6->width) * pCg6->width; pExa->offScreenBase = pCg6->width * pCg6->height; /* * our blitter can't deal with variable pitches */ pExa->pixmapOffsetAlign = pCg6->width; pExa->pixmapPitchAlign = pCg6->width; pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; pExa->maxX = 4096; pExa->maxY = 4096; pExa->WaitMarker = Cg6WaitMarker; pExa->PrepareSolid = Cg6PrepareSolid; pExa->Solid = Cg6Solid; pExa->DoneSolid = Cg6DoneCopy; pExa->PrepareCopy = Cg6PrepareCopy; pExa->Copy = Cg6Copy; pExa->DoneCopy = Cg6DoneCopy; pExa->UploadToScreen = Cg6UploadToScreen; pExa->DownloadFromScreen = Cg6DownloadFromScreen; return exaDriverInit(pScreen, pExa);; }