pm2_exa.c revision c2fa0f52
1b3d5324cSmacallan/* 2b3d5324cSmacallan * Copyright 1997-2001 by Alan Hourihane, Wigan, England. 3b3d5324cSmacallan * Copyright 2016 by Michael Lorenz 4b3d5324cSmacallan * 5b3d5324cSmacallan * Permission to use, copy, modify, distribute, and sell this software and its 6b3d5324cSmacallan * documentation for any purpose is hereby granted without fee, provided that 7b3d5324cSmacallan * the above copyright notice appear in all copies and that both that 8b3d5324cSmacallan * copyright notice and this permission notice appear in supporting 9b3d5324cSmacallan * documentation, and that the name of Alan Hourihane not be used in 10b3d5324cSmacallan * advertising or publicity pertaining to distribution of the software without 11b3d5324cSmacallan * specific, written prior permission. Alan Hourihane makes no representations 12b3d5324cSmacallan * about the suitability of this software for any purpose. It is provided 13b3d5324cSmacallan * "as is" without express or implied warranty. 14b3d5324cSmacallan * 15b3d5324cSmacallan * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16b3d5324cSmacallan * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17b3d5324cSmacallan * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18b3d5324cSmacallan * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19b3d5324cSmacallan * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20b3d5324cSmacallan * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21b3d5324cSmacallan * PERFORMANCE OF THIS SOFTWARE. 22b3d5324cSmacallan * 23b3d5324cSmacallan * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 24b3d5324cSmacallan * Dirk Hohndel, <hohndel@suse.de> 25b3d5324cSmacallan * Stefan Dirsch, <sndirsch@suse.de> 26b3d5324cSmacallan * Mark Vojkovich, <mvojkovi@ucsd.edu> 27b3d5324cSmacallan * Michel Dänzer, <michdaen@iiic.ethz.ch> 28b3d5324cSmacallan * 29b3d5324cSmacallan * this work is sponsored by S.u.S.E. GmbH, Fuerth, Elsa GmbH, Aachen and 30b3d5324cSmacallan * Siemens Nixdorf Informationssysteme 31b3d5324cSmacallan * 32b3d5324cSmacallan * Permedia 2 accelerated options, EXA style. 33b3d5324cSmacallan */ 34b3d5324cSmacallan 35b3d5324cSmacallan#ifdef HAVE_CONFIG_H 36b3d5324cSmacallan#include "config.h" 37b3d5324cSmacallan#endif 38b3d5324cSmacallan 39b3d5324cSmacallan#include <X11/Xarch.h> 40b3d5324cSmacallan#include "xf86.h" 41b3d5324cSmacallan#include "xf86_OSproc.h" 42b3d5324cSmacallan 43b3d5324cSmacallan#include "xf86Pci.h" 44b3d5324cSmacallan 45b3d5324cSmacallan#include "glint_regs.h" 46b3d5324cSmacallan#include "glint.h" 47b3d5324cSmacallan 48b3d5324cSmacallan//#define PM2_DEBUG 49b3d5324cSmacallan 50b3d5324cSmacallan#ifdef PM2_DEBUG 51b3d5324cSmacallan#define STATIC static 52b3d5324cSmacallan#define ENTER xf86Msg(X_ERROR, "%s>\n", __func__); 53b3d5324cSmacallan#define DPRINTF xf86Msg 54b3d5324cSmacallan#else 55b3d5324cSmacallan#define ENTER 56b3d5324cSmacallan#define STATIC 57b3d5324cSmacallan#define DPRINTF while (0) xf86Msg 58b3d5324cSmacallan#endif 59b3d5324cSmacallan 60b3d5324cSmacallanSTATIC void 61b3d5324cSmacallanPm2WaitMarker(ScreenPtr pScreen, int Marker) 62b3d5324cSmacallan{ 63b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 64b3d5324cSmacallan 65b3d5324cSmacallan Permedia2Sync(pScrn); 66b3d5324cSmacallan} 67b3d5324cSmacallan 68b3d5324cSmacallanSTATIC Bool 69b3d5324cSmacallanPm2PrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, 70b3d5324cSmacallan int xdir, int ydir, int rop, Pixel planemask) 71b3d5324cSmacallan{ 72b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 73b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 74b3d5324cSmacallan 75b3d5324cSmacallan ENTER; 76b3d5324cSmacallan 77b3d5324cSmacallan pGlint->BltScanDirection = 0; 78b3d5324cSmacallan if (xdir == 1) pGlint->BltScanDirection |= XPositive; 79b3d5324cSmacallan if (ydir == 1) pGlint->BltScanDirection |= YPositive; 80b3d5324cSmacallan 81b3d5324cSmacallan GLINT_WAIT(4); 82b3d5324cSmacallan DO_PLANEMASK(planemask); 83b3d5324cSmacallan 84b3d5324cSmacallan GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode); 85b3d5324cSmacallan if ((rop == GXset) || (rop == GXclear)) { 86b3d5324cSmacallan pGlint->FrameBufferReadMode = pGlint->pprod; 87b3d5324cSmacallan } else 88b3d5324cSmacallan if ((rop == GXcopy) || (rop == GXcopyInverted)) { 89b3d5324cSmacallan pGlint->FrameBufferReadMode = pGlint->pprod |FBRM_SrcEnable; 90b3d5324cSmacallan } else { 91b3d5324cSmacallan pGlint->FrameBufferReadMode = pGlint->pprod | FBRM_SrcEnable | 92b3d5324cSmacallan FBRM_DstEnable; 93b3d5324cSmacallan } 94b3d5324cSmacallan LOADROP(rop); 95b3d5324cSmacallan pGlint->srcoff = exaGetPixmapOffset(pSrcPixmap); 96b3d5324cSmacallan return TRUE; 97b3d5324cSmacallan} 98b3d5324cSmacallan 99b3d5324cSmacallanSTATIC void 100b3d5324cSmacallanPm2Copy(PixmapPtr pDstPixmap, 101b3d5324cSmacallan int srcX, int srcY, int dstX, int dstY, int w, int h) 102b3d5324cSmacallan{ 103b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 104b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 105b3d5324cSmacallan int align; 106b3d5324cSmacallan int dstoff = exaGetPixmapOffset(pDstPixmap); 107b3d5324cSmacallan int pitch = exaGetPixmapPitch(pDstPixmap); 108b3d5324cSmacallan 109b3d5324cSmacallan ENTER; 110b3d5324cSmacallan 111b3d5324cSmacallan /* assuming constant pitch for now */ 112b3d5324cSmacallan srcY += pGlint->srcoff / pitch; 113b3d5324cSmacallan dstY += dstoff / pitch; 114b3d5324cSmacallan 115b3d5324cSmacallan /* We can only use GXcopy for Packed modes */ 116b3d5324cSmacallan if ((pGlint->ROP != GXcopy) || (pScrn->bitsPerPixel != 8)) { 117b3d5324cSmacallan GLINT_WAIT(5); 118b3d5324cSmacallan GLINT_WRITE_REG(pGlint->FrameBufferReadMode, FBReadMode); 119b3d5324cSmacallan Permedia2LoadCoord(pScrn, dstX, dstY, w, h); 120b3d5324cSmacallan GLINT_WRITE_REG(((srcY - dstY) & 0x0FFF) << 16 | 121b3d5324cSmacallan ((srcX - dstX) & 0x0FFF), FBSourceDelta); 122b3d5324cSmacallan } else { 123b3d5324cSmacallan align = (dstX & pGlint->bppalign) - (srcX & pGlint->bppalign); 124b3d5324cSmacallan GLINT_WAIT(6); 125b3d5324cSmacallan GLINT_WRITE_REG(pGlint->FrameBufferReadMode|FBRM_Packed, FBReadMode); 126b3d5324cSmacallan Permedia2LoadCoord(pScrn, dstX >> pGlint->BppShift, dstY, 127b3d5324cSmacallan (w + 7) >> pGlint->BppShift, h); 128b3d5324cSmacallan GLINT_WRITE_REG(align << 29 | dstX << 16 | (dstX + w), PackedDataLimits); 129b3d5324cSmacallan GLINT_WRITE_REG(((srcX - dstX) & 0x0FFF) << 16 | 130b3d5324cSmacallan (((srcX & ~pGlint->bppalign) - (dstX & ~pGlint->bppalign)) & 0x0FFF), 131b3d5324cSmacallan FBSourceDelta); 132b3d5324cSmacallan } 133b3d5324cSmacallan GLINT_WRITE_REG(PrimitiveRectangle | pGlint->BltScanDirection, Render); 134b3d5324cSmacallan 135b3d5324cSmacallan exaMarkSync(pDstPixmap->drawable.pScreen); 136b3d5324cSmacallan} 137b3d5324cSmacallan 138b3d5324cSmacallanSTATIC void 139b3d5324cSmacallanPm2DoneCopy(PixmapPtr pPixmap) 140b3d5324cSmacallan{ 141b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 142b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 143b3d5324cSmacallan 144b3d5324cSmacallan} 145b3d5324cSmacallan 146b3d5324cSmacallanSTATIC Bool 147b3d5324cSmacallanPm2PrepareSolid(PixmapPtr pPixmap, int rop, Pixel planemask, Pixel color) 148b3d5324cSmacallan{ 149b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 150b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 151b3d5324cSmacallan 152b3d5324cSmacallan ENTER; 153b3d5324cSmacallan 154b3d5324cSmacallan REPLICATE(color); 155b3d5324cSmacallan 156b3d5324cSmacallan GLINT_WAIT(6); 157b3d5324cSmacallan DO_PLANEMASK(planemask); 158b3d5324cSmacallan if (rop == GXcopy) { 159b3d5324cSmacallan GLINT_WRITE_REG(UNIT_DISABLE, ColorDDAMode); 160b3d5324cSmacallan GLINT_WRITE_REG(pGlint->pprod, FBReadMode); 161b3d5324cSmacallan GLINT_WRITE_REG(color, FBBlockColor); 162b3d5324cSmacallan } else { 163b3d5324cSmacallan GLINT_WRITE_REG(UNIT_ENABLE, ColorDDAMode); 164b3d5324cSmacallan GLINT_WRITE_REG(color, ConstantColor); 165b3d5324cSmacallan /* We can use Packed mode for filling solid non-GXcopy rasters */ 166b3d5324cSmacallan GLINT_WRITE_REG(pGlint->pprod|FBRM_DstEnable|FBRM_Packed, FBReadMode); 167b3d5324cSmacallan } 168b3d5324cSmacallan LOADROP(rop); 169b3d5324cSmacallan 170b3d5324cSmacallan return TRUE; 171b3d5324cSmacallan} 172b3d5324cSmacallan 173b3d5324cSmacallanSTATIC void 174b3d5324cSmacallanPm2Solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) 175b3d5324cSmacallan{ 176b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 177b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 178b3d5324cSmacallan int offset = exaGetPixmapOffset(pPixmap); 179b3d5324cSmacallan int pitch = exaGetPixmapPitch(pPixmap); 180b3d5324cSmacallan int w = x2 - x1, h = y2 - y1; 181b3d5324cSmacallan int speed = 0; 182b3d5324cSmacallan 183b3d5324cSmacallan ENTER; 184b3d5324cSmacallan 185b3d5324cSmacallan y1 += offset / pitch; 186b3d5324cSmacallan if (pGlint->ROP == GXcopy) { 187b3d5324cSmacallan GLINT_WAIT(3); 188b3d5324cSmacallan Permedia2LoadCoord(pScrn, x1, y1, w, h); 189b3d5324cSmacallan speed = FastFillEnable; 190b3d5324cSmacallan } else { 191b3d5324cSmacallan GLINT_WAIT(4); 192b3d5324cSmacallan Permedia2LoadCoord(pScrn, x1 >> pGlint->BppShift, y1, 193b3d5324cSmacallan (w + 7) >> pGlint->BppShift, h); 194b3d5324cSmacallan GLINT_WRITE_REG(x1 << 16 | (x1 + w), PackedDataLimits); 195b3d5324cSmacallan speed = 0; 196b3d5324cSmacallan } 197b3d5324cSmacallan GLINT_WRITE_REG(PrimitiveRectangle | XPositive | YPositive | speed, Render); 198b3d5324cSmacallan 199b3d5324cSmacallan exaMarkSync(pPixmap->drawable.pScreen); 200b3d5324cSmacallan} 201b3d5324cSmacallan 202b3d5324cSmacallan/* 203b3d5324cSmacallan * Memcpy-based UTS. 204b3d5324cSmacallan */ 205b3d5324cSmacallanSTATIC Bool 206b3d5324cSmacallanPm2UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 207b3d5324cSmacallan char *src, int src_pitch) 208b3d5324cSmacallan{ 209b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 210b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 211c2fa0f52Smacallan int offset = exaGetPixmapOffset(pDst); 212c2fa0f52Smacallan unsigned char *dst = pGlint->FbBase + offset; 213c2fa0f52Smacallan CARD32 *s; 214c2fa0f52Smacallan int dst_pitch = exaGetPixmapPitch(pDst); 215b3d5324cSmacallan 216b3d5324cSmacallan int bpp = pDst->drawable.bitsPerPixel; 217b3d5324cSmacallan int cpp = (bpp + 7) >> 3; 218b3d5324cSmacallan int wBytes = w * cpp; 219a2587576Smacallan int xx, i, fs = pGlint->FIFOSize, chunk, adr; 220b3d5324cSmacallan 221b3d5324cSmacallan ENTER; 222b3d5324cSmacallan 223a2587576Smacallan if (bpp < 24) { 224a2587576Smacallan /* for now */ 225a2587576Smacallan dst += (x * cpp) + (y * dst_pitch); 226b3d5324cSmacallan 227a2587576Smacallan Permedia2Sync(pScrn); 228a2587576Smacallan 229a2587576Smacallan while (h--) { 230a2587576Smacallan memcpy(dst, src, wBytes); 231a2587576Smacallan src += src_pitch; 232a2587576Smacallan dst += dst_pitch; 233a2587576Smacallan } 234a2587576Smacallan } else { 235a2587576Smacallan /* use host blit */ 236a2587576Smacallan y += offset / dst_pitch; 237a2587576Smacallan adr = y * (dst_pitch >> 2) + x; 238a2587576Smacallan while (h--) { 239c2fa0f52Smacallan s = (CARD32 *)src; 240a2587576Smacallan xx = w; 241a2587576Smacallan GLINT_WAIT(1); 242a2587576Smacallan GLINT_WRITE_REG(adr, TextureDownloadOffset); 243a2587576Smacallan while (xx > 0) { 244a2587576Smacallan chunk = min(fs - 1, xx); 245a2587576Smacallan GLINT_WAIT(chunk); 246a2587576Smacallan GLINT_WRITE_REG(((chunk - 1) << 16) | (0x11 << 4) | 247a2587576Smacallan 0x0d, OutputFIFO); 248a2587576Smacallan GLINT_MoveDWORDS( 249a2587576Smacallan (CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4), 250a2587576Smacallan s, chunk); 251a2587576Smacallan xx -= chunk; 252a2587576Smacallan s += chunk; 253a2587576Smacallan } 254a2587576Smacallan adr += (dst_pitch >> 2); 255a2587576Smacallan src += src_pitch; 256a2587576Smacallan } 257a2587576Smacallan exaMarkSync(pDst->drawable.pScreen); 258b3d5324cSmacallan } 259b3d5324cSmacallan return TRUE; 260b3d5324cSmacallan} 261b3d5324cSmacallan 262b3d5324cSmacallan/* 263b3d5324cSmacallan * Memcpy-based DFS. 264b3d5324cSmacallan */ 265b3d5324cSmacallanSTATIC Bool 266b3d5324cSmacallanPm2DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 267b3d5324cSmacallan char *dst, int dst_pitch) 268b3d5324cSmacallan{ 269b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 270c2fa0f52Smacallan GLINTPtr pGlint = GLINTPTR(pScrn); 271c2fa0f52Smacallan unsigned char *src = pGlint->FbBase + exaGetPixmapOffset(pSrc); 272c2fa0f52Smacallan int src_pitch = exaGetPixmapPitch(pSrc); 273b3d5324cSmacallan 274b3d5324cSmacallan ENTER; 275b3d5324cSmacallan int bpp = pSrc->drawable.bitsPerPixel; 276b3d5324cSmacallan int cpp = (bpp + 7) >> 3; 277b3d5324cSmacallan int wBytes = w * cpp; 278b3d5324cSmacallan 279b3d5324cSmacallan src += (x * cpp) + (y * src_pitch); 280b3d5324cSmacallan 2814bd90d63Smacallan Permedia2Sync(pScrn); 282b3d5324cSmacallan 283b3d5324cSmacallan while (h--) { 284b3d5324cSmacallan memcpy(dst, src, wBytes); 285b3d5324cSmacallan src += src_pitch; 286b3d5324cSmacallan dst += dst_pitch; 287b3d5324cSmacallan } 288b3d5324cSmacallan 289b3d5324cSmacallan return TRUE; 290b3d5324cSmacallan} 291b3d5324cSmacallan 292b3d5324cSmacallanBool 293b3d5324cSmacallanPm2InitEXA(ScreenPtr pScreen) 294b3d5324cSmacallan{ 295b3d5324cSmacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 296b3d5324cSmacallan GLINTPtr pGlint = GLINTPTR(pScrn); 297b3d5324cSmacallan ExaDriverPtr pExa; 298eaa0d4a1Smacallan int stride, lines; 299b3d5324cSmacallan 300b3d5324cSmacallan ENTER; 301b3d5324cSmacallan 302b3d5324cSmacallan pExa = exaDriverAlloc(); 303b3d5324cSmacallan if (!pExa) 304b3d5324cSmacallan return FALSE; 305b3d5324cSmacallan 306b3d5324cSmacallan pGlint->pExa = pExa; 307b3d5324cSmacallan 308b3d5324cSmacallan pExa->exa_major = EXA_VERSION_MAJOR; 309b3d5324cSmacallan pExa->exa_minor = EXA_VERSION_MINOR; 310b3d5324cSmacallan 311b3d5324cSmacallan pExa->memoryBase = pGlint->FbBase; 312b3d5324cSmacallan stride = pScrn->displayWidth * (pScrn->bitsPerPixel >> 3); 313eaa0d4a1Smacallan lines = min(pGlint->FbMapSize / stride, 2047); 314eaa0d4a1Smacallan pExa->memorySize = lines * stride; 315b3d5324cSmacallan DPRINTF(X_ERROR, "stride: %d\n", stride); 316b3d5324cSmacallan DPRINTF(X_ERROR, "pprod: %08x\n", pGlint->pprod); 317b3d5324cSmacallan pExa->offScreenBase = stride * pScrn->virtualY; 318b3d5324cSmacallan 319b3d5324cSmacallan /* for now, until I figure out how to do variable stride */ 320b3d5324cSmacallan pExa->pixmapOffsetAlign = stride; 321b3d5324cSmacallan pExa->pixmapPitchAlign = stride; 322b3d5324cSmacallan 323eaa0d4a1Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS; 324b3d5324cSmacallan 3254bd90d63Smacallan pExa->maxX = 2048; 3264bd90d63Smacallan pExa->maxY = 2048; 327b3d5324cSmacallan 328b3d5324cSmacallan pExa->WaitMarker = Pm2WaitMarker; 329b3d5324cSmacallan 330b3d5324cSmacallan pExa->PrepareSolid = Pm2PrepareSolid; 331b3d5324cSmacallan pExa->Solid = Pm2Solid; 332b3d5324cSmacallan pExa->DoneSolid = Pm2DoneCopy; 333b3d5324cSmacallan pExa->PrepareCopy = Pm2PrepareCopy; 334b3d5324cSmacallan pExa->Copy = Pm2Copy; 335b3d5324cSmacallan pExa->DoneCopy = Pm2DoneCopy; 336b3d5324cSmacallan 337b3d5324cSmacallan /* EXA hits more optimized paths when it does not have to fallback 338b3d5324cSmacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 339b3d5324cSmacallan */ 340b3d5324cSmacallan pExa->UploadToScreen = Pm2UploadToScreen; 341b3d5324cSmacallan pExa->DownloadFromScreen = Pm2DownloadFromScreen; 342b3d5324cSmacallan 343b3d5324cSmacallan Permedia2InitializeEngine(pScrn); 344b3d5324cSmacallan 345b3d5324cSmacallan return exaDriverInit(pScreen, pExa); 346b3d5324cSmacallan} 347