igs_accel.c revision 9a5ed1c5
1be1ef3d3Smacallan/* 2be1ef3d3Smacallan * IGS CyberPro - hardware acceleration. 3be1ef3d3Smacallan * 4be1ef3d3Smacallan * Copyright (C) 2009 Michael Lorenz 5be1ef3d3Smacallan * 6be1ef3d3Smacallan * Permission is hereby granted, free of charge, to any person obtaining a copy 7be1ef3d3Smacallan * of this software and associated documentation files (the "Software"), to deal 8be1ef3d3Smacallan * in the Software without restriction, including without limitation the rights 9be1ef3d3Smacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10be1ef3d3Smacallan * copies of the Software, and to permit persons to whom the Software is 11be1ef3d3Smacallan * furnished to do so, subject to the following conditions: 12be1ef3d3Smacallan * 13be1ef3d3Smacallan * The above copyright notice and this permission notice shall be included in 14be1ef3d3Smacallan * all copies or substantial portions of the Software. 15be1ef3d3Smacallan * 16be1ef3d3Smacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17be1ef3d3Smacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18be1ef3d3Smacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19be1ef3d3Smacallan * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20be1ef3d3Smacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21be1ef3d3Smacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22be1ef3d3Smacallan */ 23be1ef3d3Smacallan 249a5ed1c5Smacallan/* $NetBSD: igs_accel.c,v 1.2 2009/11/21 22:22:27 macallan Exp $ */ 25be1ef3d3Smacallan 26be1ef3d3Smacallan#include <sys/types.h> 27be1ef3d3Smacallan 28be1ef3d3Smacallan#include "igs.h" 29be1ef3d3Smacallan 30be1ef3d3Smacallan/*#define DEBUG*/ 31be1ef3d3Smacallan 32be1ef3d3Smacallan#ifdef DEBUG 33be1ef3d3Smacallan#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 34be1ef3d3Smacallan#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 35be1ef3d3Smacallan#else 36be1ef3d3Smacallan#define ENTER 37be1ef3d3Smacallan#define LEAVE 38be1ef3d3Smacallan#endif 39be1ef3d3Smacallan 40be1ef3d3Smacallanstatic inline void IgsWrite1(IgsPtr fPtr, int offset, uint8_t val) 41be1ef3d3Smacallan{ 42be1ef3d3Smacallan *(fPtr->reg + offset) = val; 43be1ef3d3Smacallan} 44be1ef3d3Smacallan 45be1ef3d3Smacallan 46be1ef3d3Smacallanstatic inline void IgsWrite2(IgsPtr fPtr, int offset, uint16_t val) 47be1ef3d3Smacallan{ 48be1ef3d3Smacallan *(uint16_t *)(fPtr->reg + offset) = val; 49be1ef3d3Smacallan} 50be1ef3d3Smacallan 51be1ef3d3Smacallanstatic inline void IgsWrite4(IgsPtr fPtr, int offset, uint32_t val) 52be1ef3d3Smacallan{ 53be1ef3d3Smacallan *(uint32_t *)(fPtr->reg + offset) = val; 54be1ef3d3Smacallan} 55be1ef3d3Smacallan 56be1ef3d3Smacallanstatic inline uint8_t IgsRead1(IgsPtr fPtr, int offset) 57be1ef3d3Smacallan{ 58be1ef3d3Smacallan return *(fPtr->reg + offset); 59be1ef3d3Smacallan} 60be1ef3d3Smacallan 61be1ef3d3Smacallanstatic inline uint16_t IgsRead2(IgsPtr fPtr, int offset) 62be1ef3d3Smacallan{ 63be1ef3d3Smacallan return *(uint16_t *)(fPtr->reg + offset); 64be1ef3d3Smacallan} 65be1ef3d3Smacallan 66be1ef3d3Smacallanstatic void 67be1ef3d3SmacallanIgsWaitMarker(ScreenPtr pScreen, int Marker) 68be1ef3d3Smacallan{ 69be1ef3d3Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 70be1ef3d3Smacallan IgsPtr fPtr = IGSPTR(pScrn); 71be1ef3d3Smacallan int bail = 0x0fffffff; 729a5ed1c5Smacallan 73be1ef3d3Smacallan ENTER; 74be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, (fPtr->info.depth >> 3) - 1); 75be1ef3d3Smacallan while ((IgsRead1(fPtr, 76be1ef3d3Smacallan IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ) != 0) 77be1ef3d3Smacallan && (bail > 0)) { 78be1ef3d3Smacallan bail--; 79be1ef3d3Smacallan usleep(1); 80be1ef3d3Smacallan } 81be1ef3d3Smacallan 82be1ef3d3Smacallan /* reset the coprocessor if we run into a timeout */ 83be1ef3d3Smacallan if (bail == 0) { 84be1ef3d3Smacallan xf86Msg(X_ERROR, "%s: timeout\n", __func__); 85be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 86be1ef3d3Smacallan } 87be1ef3d3Smacallan LEAVE; 88be1ef3d3Smacallan} 89be1ef3d3Smacallan 90be1ef3d3Smacallanstatic int 91be1ef3d3SmacallanIgsMarkSync(ScreenPtr pScreenInfo) 92be1ef3d3Smacallan{ 939a5ed1c5Smacallan ENTER; 949a5ed1c5Smacallan return 0; 95be1ef3d3Smacallan} 96be1ef3d3Smacallan 97be1ef3d3Smacallanstatic void 98be1ef3d3SmacallanIgsWaitReady(IgsPtr fPtr) 99be1ef3d3Smacallan{ 100be1ef3d3Smacallan int bail = 0x0fffffff; 1019a5ed1c5Smacallan 102be1ef3d3Smacallan ENTER; 103be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, (fPtr->info.depth >> 3) - 1); 104be1ef3d3Smacallan while (((IgsRead1(fPtr, 105be1ef3d3Smacallan IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 106be1ef3d3Smacallan && (bail > 0)) { 107be1ef3d3Smacallan bail--; 108be1ef3d3Smacallan usleep(1); 109be1ef3d3Smacallan } 110be1ef3d3Smacallan 111be1ef3d3Smacallan /* reset the coprocessor if we run into a timeout */ 112be1ef3d3Smacallan if (bail == 0) { 113be1ef3d3Smacallan xf86Msg(X_ERROR, "%s: timeout\n", __func__); 114be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 115be1ef3d3Smacallan } 116be1ef3d3Smacallan LEAVE; 117be1ef3d3Smacallan} 118be1ef3d3Smacallan 119be1ef3d3Smacallanstatic Bool 120be1ef3d3SmacallanIgsPrepareCopy 121be1ef3d3Smacallan( 122be1ef3d3Smacallan PixmapPtr pSrcPixmap, 123be1ef3d3Smacallan PixmapPtr pDstPixmap, 124be1ef3d3Smacallan int xdir, 125be1ef3d3Smacallan int ydir, 126be1ef3d3Smacallan int alu, 127be1ef3d3Smacallan Pixel planemask 128be1ef3d3Smacallan) 129be1ef3d3Smacallan{ 130be1ef3d3Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 131be1ef3d3Smacallan IgsPtr fPtr = IGSPTR(pScrn); 132be1ef3d3Smacallan 133be1ef3d3Smacallan ENTER; 134be1ef3d3Smacallan fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC | 135be1ef3d3Smacallan IGS_COP_PPM_FIXED_FG; 136be1ef3d3Smacallan if (xdir < 0) 137be1ef3d3Smacallan fPtr->cmd |= IGS_COP_OCTANT_X_NEG; 138be1ef3d3Smacallan if (ydir < 0) 139be1ef3d3Smacallan fPtr->cmd |= IGS_COP_OCTANT_Y_NEG; 140be1ef3d3Smacallan 141be1ef3d3Smacallan IgsWaitReady(fPtr); 142be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 143be1ef3d3Smacallan fPtr->srcoff = exaGetPixmapOffset(pSrcPixmap) >> fPtr->shift; 144be1ef3d3Smacallan fPtr->srcpitch = exaGetPixmapPitch(pSrcPixmap) >> fPtr->shift; 145be1ef3d3Smacallan 146be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_SRC_MAP_WIDTH_REG, fPtr->srcpitch - 1); 147be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 148be1ef3d3Smacallan (exaGetPixmapPitch(pDstPixmap) >> fPtr->shift) - 1); 149be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 150be1ef3d3Smacallan IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 151be1ef3d3Smacallan LEAVE; 152be1ef3d3Smacallan return TRUE; 153be1ef3d3Smacallan} 154be1ef3d3Smacallan 155be1ef3d3Smacallanstatic void 156be1ef3d3SmacallanIgsCopy 157be1ef3d3Smacallan( 158be1ef3d3Smacallan PixmapPtr pDstPixmap, 159be1ef3d3Smacallan int srcX, 160be1ef3d3Smacallan int srcY, 161be1ef3d3Smacallan int dstX, 162be1ef3d3Smacallan int dstY, 163be1ef3d3Smacallan int w, 164be1ef3d3Smacallan int h 165be1ef3d3Smacallan) 166be1ef3d3Smacallan{ 167be1ef3d3Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 168be1ef3d3Smacallan IgsPtr fPtr = IGSPTR(pScrn); 169be1ef3d3Smacallan int dstpitch, dstoff; 170be1ef3d3Smacallan 171be1ef3d3Smacallan if (fPtr->cmd & IGS_COP_OCTANT_X_NEG) { 172be1ef3d3Smacallan srcX += (w - 1); 173be1ef3d3Smacallan dstX += (w - 1); 174be1ef3d3Smacallan } 175be1ef3d3Smacallan 176be1ef3d3Smacallan if (fPtr->cmd & IGS_COP_OCTANT_Y_NEG) { 177be1ef3d3Smacallan srcY += (h - 1); 178be1ef3d3Smacallan dstY += (h - 1); 179be1ef3d3Smacallan } 180be1ef3d3Smacallan IgsWaitReady(fPtr); 181be1ef3d3Smacallan IgsWrite4(fPtr, IGS_COP_SRC_START_REG, fPtr->srcoff + srcX + 182be1ef3d3Smacallan fPtr->srcpitch * srcY); 183be1ef3d3Smacallan dstpitch = exaGetPixmapPitch(pDstPixmap) >> fPtr->shift; 184be1ef3d3Smacallan dstoff = exaGetPixmapOffset(pDstPixmap) >> fPtr->shift; 185be1ef3d3Smacallan IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + dstX + 186be1ef3d3Smacallan dstpitch * dstY); 187be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 188be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 189be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 190be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 191be1ef3d3Smacallan LEAVE; 192be1ef3d3Smacallan} 193be1ef3d3Smacallan 194be1ef3d3Smacallanstatic void 195be1ef3d3SmacallanIgsDoneCopy(PixmapPtr pDstPixmap) 196be1ef3d3Smacallan{ 197be1ef3d3Smacallan ENTER; 198be1ef3d3Smacallan LEAVE; 199be1ef3d3Smacallan} 200be1ef3d3Smacallan 201be1ef3d3Smacallanstatic Bool 202be1ef3d3SmacallanIgsPrepareSolid( 203be1ef3d3Smacallan PixmapPtr pPixmap, 204be1ef3d3Smacallan int alu, 205be1ef3d3Smacallan Pixel planemask, 206be1ef3d3Smacallan Pixel fg) 207be1ef3d3Smacallan{ 208be1ef3d3Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 209be1ef3d3Smacallan IgsPtr fPtr = IGSPTR(pScrn); 210be1ef3d3Smacallan 211be1ef3d3Smacallan ENTER; 212be1ef3d3Smacallan fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_PPM_FIXED_FG; 213be1ef3d3Smacallan 214be1ef3d3Smacallan IgsWaitReady(fPtr); 215be1ef3d3Smacallan 216be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 217be1ef3d3Smacallan 218be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 219be1ef3d3Smacallan (exaGetPixmapPitch(pPixmap) >> fPtr->shift) - 1); 220be1ef3d3Smacallan IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 221be1ef3d3Smacallan IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 222be1ef3d3Smacallan IgsWrite4(fPtr, IGS_COP_FG_REG, fg); 223be1ef3d3Smacallan LEAVE; 224be1ef3d3Smacallan return TRUE; 225be1ef3d3Smacallan} 226be1ef3d3Smacallan 227be1ef3d3Smacallanstatic void 228be1ef3d3SmacallanIgsSolid( 229be1ef3d3Smacallan PixmapPtr pPixmap, 230be1ef3d3Smacallan int x1, 231be1ef3d3Smacallan int y1, 232be1ef3d3Smacallan int x2, 233be1ef3d3Smacallan int y2) 234be1ef3d3Smacallan{ 235be1ef3d3Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 236be1ef3d3Smacallan IgsPtr fPtr = IGSPTR(pScrn); 237be1ef3d3Smacallan int w = x2 - x1, h = y2 - y1, dstoff, dstpitch; 238be1ef3d3Smacallan 239be1ef3d3Smacallan ENTER; 240be1ef3d3Smacallan IgsWaitReady(fPtr); 241be1ef3d3Smacallan dstpitch = exaGetPixmapPitch(pPixmap) >> fPtr->shift; 242be1ef3d3Smacallan dstoff = exaGetPixmapOffset(pPixmap) >> fPtr->shift; 243be1ef3d3Smacallan IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + x1 + 244be1ef3d3Smacallan dstpitch * y1); 245be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 246be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 247be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 248be1ef3d3Smacallan IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 249be1ef3d3Smacallan} 250be1ef3d3Smacallan 251be1ef3d3Smacallan/* 252be1ef3d3Smacallan * Memcpy-based UTS. 253be1ef3d3Smacallan */ 254be1ef3d3Smacallanstatic Bool 255be1ef3d3SmacallanIgsUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 256be1ef3d3Smacallan char *src, int src_pitch) 257be1ef3d3Smacallan{ 2589a5ed1c5Smacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 2599a5ed1c5Smacallan IgsPtr fPtr = IGSPTR(pScrn); 2609a5ed1c5Smacallan char *dst = fPtr->fbmem + exaGetPixmapOffset(pDst); 2619a5ed1c5Smacallan int dst_pitch = exaGetPixmapPitch(pDst); 262be1ef3d3Smacallan 2639a5ed1c5Smacallan int bpp = pDst->drawable.bitsPerPixel; 2649a5ed1c5Smacallan int cpp = (bpp + 7) / 8; 2659a5ed1c5Smacallan int wBytes = w * cpp; 266be1ef3d3Smacallan 2679a5ed1c5Smacallan ENTER; 2689a5ed1c5Smacallan dst += (x * cpp) + (y * dst_pitch); 269be1ef3d3Smacallan 2709a5ed1c5Smacallan while (h--) { 2719a5ed1c5Smacallan memcpy(dst, src, wBytes); 2729a5ed1c5Smacallan src += src_pitch; 2739a5ed1c5Smacallan dst += dst_pitch; 2749a5ed1c5Smacallan } 2759a5ed1c5Smacallan LEAVE; 2769a5ed1c5Smacallan return TRUE; 277be1ef3d3Smacallan} 278be1ef3d3Smacallan 279be1ef3d3Smacallan/* 280be1ef3d3Smacallan * Memcpy-based DFS. 281be1ef3d3Smacallan */ 282be1ef3d3Smacallanstatic Bool 283be1ef3d3SmacallanIgsDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 284be1ef3d3Smacallan char *dst, int dst_pitch) 285be1ef3d3Smacallan{ 2869a5ed1c5Smacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 2879a5ed1c5Smacallan IgsPtr fPtr = IGSPTR(pScrn); 2889a5ed1c5Smacallan char *src = fPtr->fbmem + exaGetPixmapOffset(pSrc); 2899a5ed1c5Smacallan int src_pitch = exaGetPixmapPitch(pSrc); 290be1ef3d3Smacallan 2919a5ed1c5Smacallan int bpp = pSrc->drawable.bitsPerPixel; 2929a5ed1c5Smacallan int cpp = (bpp + 7) / 8; 2939a5ed1c5Smacallan int wBytes = w * cpp; 294be1ef3d3Smacallan 2959a5ed1c5Smacallan ENTER; 2969a5ed1c5Smacallan src += (x * cpp) + (y * src_pitch); 297be1ef3d3Smacallan 2989a5ed1c5Smacallan while (h--) { 2999a5ed1c5Smacallan memcpy(dst, src, wBytes); 3009a5ed1c5Smacallan src += src_pitch; 3019a5ed1c5Smacallan dst += dst_pitch; 3029a5ed1c5Smacallan } 3039a5ed1c5Smacallan LEAVE; 3049a5ed1c5Smacallan return TRUE; 305be1ef3d3Smacallan} 306be1ef3d3Smacallan 307be1ef3d3SmacallanBool 308be1ef3d3SmacallanIgsInitAccel(ScreenPtr pScreen) 309be1ef3d3Smacallan{ 3109a5ed1c5Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3119a5ed1c5Smacallan IgsPtr fPtr = IGSPTR(pScrn); 3129a5ed1c5Smacallan ExaDriverPtr pExa; 3139a5ed1c5Smacallan 3149a5ed1c5Smacallan pExa = exaDriverAlloc(); 3159a5ed1c5Smacallan if (!pExa) 3169a5ed1c5Smacallan return FALSE; 3179a5ed1c5Smacallan 3189a5ed1c5Smacallan fPtr->pExa = pExa; 3199a5ed1c5Smacallan 3209a5ed1c5Smacallan pExa->exa_major = EXA_VERSION_MAJOR; 3219a5ed1c5Smacallan pExa->exa_minor = EXA_VERSION_MINOR; 3229a5ed1c5Smacallan 3239a5ed1c5Smacallan pExa->memoryBase = fPtr->fbmem; 324be1ef3d3Smacallan pExa->memorySize = fPtr->fbmem_len; 325be1ef3d3Smacallan pExa->offScreenBase = fPtr->linebytes * fPtr->info.height; 326be1ef3d3Smacallan pExa->pixmapOffsetAlign = 4; 327be1ef3d3Smacallan pExa->pixmapPitchAlign = 4; 328be1ef3d3Smacallan 3299a5ed1c5Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS; 330be1ef3d3Smacallan 3319a5ed1c5Smacallan pExa->maxX = 2048; 3329a5ed1c5Smacallan pExa->maxY = 2048; 333be1ef3d3Smacallan 3349a5ed1c5Smacallan pExa->MarkSync = IgsMarkSync; 3359a5ed1c5Smacallan pExa->WaitMarker = IgsWaitMarker; 3369a5ed1c5Smacallan pExa->PrepareSolid = IgsPrepareSolid; 3379a5ed1c5Smacallan pExa->Solid = IgsSolid; 3389a5ed1c5Smacallan pExa->DoneSolid = IgsDoneCopy; 3399a5ed1c5Smacallan pExa->PrepareCopy = IgsPrepareCopy; 3409a5ed1c5Smacallan pExa->Copy = IgsCopy; 3419a5ed1c5Smacallan pExa->DoneCopy = IgsDoneCopy; 342be1ef3d3Smacallan 343be1ef3d3Smacallan switch(fPtr->info.depth) { 344be1ef3d3Smacallan case 8: 345be1ef3d3Smacallan fPtr->shift = 0; 346be1ef3d3Smacallan break; 347be1ef3d3Smacallan case 16: 348be1ef3d3Smacallan fPtr->shift = 1; 349be1ef3d3Smacallan break; 350be1ef3d3Smacallan case 32: 351be1ef3d3Smacallan fPtr->shift = 2; 352be1ef3d3Smacallan break; 353be1ef3d3Smacallan } 3549a5ed1c5Smacallan /* EXA hits more optimized paths when it does not have to fallback 3559a5ed1c5Smacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 3569a5ed1c5Smacallan */ 3579a5ed1c5Smacallan pExa->UploadToScreen = IgsUploadToScreen; 3589a5ed1c5Smacallan pExa->DownloadFromScreen = IgsDownloadFromScreen; 3599a5ed1c5Smacallan 3609a5ed1c5Smacallan return exaDriverInit(pScreen, pExa); 361be1ef3d3Smacallan} 362