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