igs_accel.c revision 83616484
1/* 2 * IGS CyberPro - hardware acceleration. 3 * 4 * Copyright (C) 2009 Michael Lorenz 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24/* $NetBSD: igs_accel.c,v 1.4 2010/05/20 19:45:21 macallan Exp $ */ 25 26#include <sys/types.h> 27 28#include "igs.h" 29 30/*#define DEBUG*/ 31 32#ifdef DEBUG 33#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 34#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 35#else 36#define ENTER 37#define LEAVE 38#endif 39 40static inline void IgsWrite1(IgsPtr fPtr, int offset, uint8_t val) 41{ 42 *(fPtr->reg + offset) = val; 43} 44 45 46static inline void IgsWrite2(IgsPtr fPtr, int offset, uint16_t val) 47{ 48 *(uint16_t *)(fPtr->reg + offset) = val; 49} 50 51static inline void IgsWrite4(IgsPtr fPtr, int offset, uint32_t val) 52{ 53 *(uint32_t *)(fPtr->reg + offset) = val; 54} 55 56static inline uint8_t IgsRead1(IgsPtr fPtr, int offset) 57{ 58 return *(fPtr->reg + offset); 59} 60 61static inline uint16_t IgsRead2(IgsPtr fPtr, int offset) 62{ 63 return *(uint16_t *)(fPtr->reg + offset); 64} 65 66static void 67IgsWaitMarker(ScreenPtr pScreen, int Marker) 68{ 69 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 70 IgsPtr fPtr = IGSPTR(pScrn); 71 int bail = 0x0fffffff; 72 73 ENTER; 74 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 75 while ((IgsRead1(fPtr, 76 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ) != 0) 77 && (bail > 0)) { 78 bail--; 79 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 80 } 81 82 /* reset the coprocessor if we run into a timeout */ 83 if (bail == 0) { 84 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 85 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 86 } 87 LEAVE; 88} 89 90static int 91IgsMarkSync(ScreenPtr pScreenInfo) 92{ 93 ENTER; 94 return 0; 95} 96 97static void 98IgsWaitReady(IgsPtr fPtr) 99{ 100 int bail = 0x0fffffff; 101 102 ENTER; 103 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 104 while (((IgsRead1(fPtr, 105 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 106 && (bail > 0)) { 107 bail--; 108 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 109 } 110 111 /* reset the coprocessor if we run into a timeout */ 112 if (bail == 0) { 113 xf86Msg(X_ERROR, "%s: timeout\n", __func__); 114 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 115 } 116 LEAVE; 117} 118 119static Bool 120IgsPrepareCopy 121( 122 PixmapPtr pSrcPixmap, 123 PixmapPtr pDstPixmap, 124 int xdir, 125 int ydir, 126 int alu, 127 Pixel planemask 128) 129{ 130 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 131 IgsPtr fPtr = IGSPTR(pScrn); 132 133 ENTER; 134 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC | 135 IGS_COP_PPM_FIXED_FG; 136 if (xdir < 0) 137 fPtr->cmd |= IGS_COP_OCTANT_X_NEG; 138 if (ydir < 0) 139 fPtr->cmd |= IGS_COP_OCTANT_Y_NEG; 140 141 IgsWaitReady(fPtr); 142 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 143 fPtr->srcoff = exaGetPixmapOffset(pSrcPixmap) >> fPtr->shift; 144 fPtr->srcpitch = exaGetPixmapPitch(pSrcPixmap) >> fPtr->shift; 145 146 IgsWrite2(fPtr, IGS_COP_SRC_MAP_WIDTH_REG, fPtr->srcpitch - 1); 147 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 148 (exaGetPixmapPitch(pDstPixmap) >> fPtr->shift) - 1); 149 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 150 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 151 LEAVE; 152 return TRUE; 153} 154 155static void 156IgsCopy 157( 158 PixmapPtr pDstPixmap, 159 int srcX, 160 int srcY, 161 int dstX, 162 int dstY, 163 int w, 164 int h 165) 166{ 167 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 168 IgsPtr fPtr = IGSPTR(pScrn); 169 int dstpitch, dstoff; 170 171 if (fPtr->cmd & IGS_COP_OCTANT_X_NEG) { 172 srcX += (w - 1); 173 dstX += (w - 1); 174 } 175 176 if (fPtr->cmd & IGS_COP_OCTANT_Y_NEG) { 177 srcY += (h - 1); 178 dstY += (h - 1); 179 } 180 IgsWaitReady(fPtr); 181 IgsWrite4(fPtr, IGS_COP_SRC_START_REG, fPtr->srcoff + srcX + 182 fPtr->srcpitch * srcY); 183 dstpitch = exaGetPixmapPitch(pDstPixmap) >> fPtr->shift; 184 dstoff = exaGetPixmapOffset(pDstPixmap) >> fPtr->shift; 185 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + dstX + 186 dstpitch * dstY); 187 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 188 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 189 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 190 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 191 LEAVE; 192} 193 194static void 195IgsDoneCopy(PixmapPtr pDstPixmap) 196{ 197 ENTER; 198 LEAVE; 199} 200 201static Bool 202IgsPrepareSolid( 203 PixmapPtr pPixmap, 204 int alu, 205 Pixel planemask, 206 Pixel fg) 207{ 208 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 209 IgsPtr fPtr = IGSPTR(pScrn); 210 211 ENTER; 212 fPtr->cmd = IGS_COP_OP_PXBLT | IGS_COP_PPM_FIXED_FG; 213 214 IgsWaitReady(fPtr); 215 216 IgsWrite1(fPtr, IGS_COP_CTL_REG, 0); 217 218 IgsWrite2(fPtr, IGS_COP_DST_MAP_WIDTH_REG, 219 (exaGetPixmapPitch(pPixmap) >> fPtr->shift) - 1); 220 IgsWrite1(fPtr, IGS_COP_FG_MIX_REG, alu); 221 IgsWrite4(fPtr, IGS_PLANE_MASK_REG, planemask); 222 IgsWrite4(fPtr, IGS_COP_FG_REG, fg); 223 LEAVE; 224 return TRUE; 225} 226 227static void 228IgsSolid( 229 PixmapPtr pPixmap, 230 int x1, 231 int y1, 232 int x2, 233 int y2) 234{ 235 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 236 IgsPtr fPtr = IGSPTR(pScrn); 237 int w = x2 - x1, h = y2 - y1, dstoff, dstpitch; 238 239 ENTER; 240 IgsWaitReady(fPtr); 241 dstpitch = exaGetPixmapPitch(pPixmap) >> fPtr->shift; 242 dstoff = exaGetPixmapOffset(pPixmap) >> fPtr->shift; 243 IgsWrite4(fPtr, IGS_COP_DST_START_REG, dstoff + x1 + 244 dstpitch * y1); 245 IgsWrite2(fPtr, IGS_COP_WIDTH_REG, w - 1); 246 IgsWrite2(fPtr, IGS_COP_HEIGHT_REG, h - 1); 247 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG, fPtr->cmd & 0xffff); 248 IgsWrite2(fPtr, IGS_COP_PIXEL_OP_REG + 2, (fPtr->cmd >> 16) & 0xffff); 249} 250 251/* 252 * Memcpy-based UTS. 253 */ 254static Bool 255IgsUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 256 char *src, int src_pitch) 257{ 258 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 259 IgsPtr fPtr = IGSPTR(pScrn); 260 char *dst = fPtr->fbmem + exaGetPixmapOffset(pDst); 261 int dst_pitch = exaGetPixmapPitch(pDst); 262 263 int bpp = pDst->drawable.bitsPerPixel; 264 int cpp = (bpp + 7) >> 3; 265 int wBytes = w * cpp; 266 267 ENTER; 268 dst += (x * cpp) + (y * dst_pitch); 269 270 IgsWaitReady(fPtr); 271 272 while (h--) { 273 memcpy(dst, src, wBytes); 274 src += src_pitch; 275 dst += dst_pitch; 276 } 277 LEAVE; 278 return TRUE; 279} 280 281/* 282 * Memcpy-based DFS. 283 */ 284static Bool 285IgsDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 286 char *dst, int dst_pitch) 287{ 288 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 289 IgsPtr fPtr = IGSPTR(pScrn); 290 char *src = fPtr->fbmem + exaGetPixmapOffset(pSrc); 291 int src_pitch = exaGetPixmapPitch(pSrc); 292 293 int bpp = pSrc->drawable.bitsPerPixel; 294 int cpp = (bpp + 7) >> 3; 295 int wBytes = w * cpp; 296 297 ENTER; 298 src += (x * cpp) + (y * src_pitch); 299 300 IgsWaitReady(fPtr); 301 302 while (h--) { 303 memcpy(dst, src, wBytes); 304 src += src_pitch; 305 dst += dst_pitch; 306 } 307 LEAVE; 308 return TRUE; 309} 310 311#ifdef __arm__ 312static Bool 313IgsPrepareAccess(PixmapPtr pPix, int index) 314{ 315 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 316 IgsPtr fPtr = IGSPTR(pScrn); 317 318 IgsWaitReady(fPtr); 319 return TRUE; 320} 321 322static void 323IgsFinishAccess(PixmapPtr pPix, int index) 324{ 325} 326#endif 327 328Bool 329IgsInitAccel(ScreenPtr pScreen) 330{ 331 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 332 IgsPtr fPtr = IGSPTR(pScrn); 333 ExaDriverPtr pExa; 334 335 pExa = exaDriverAlloc(); 336 if (!pExa) 337 return FALSE; 338 339 fPtr->pExa = pExa; 340 341 pExa->exa_major = EXA_VERSION_MAJOR; 342 pExa->exa_minor = EXA_VERSION_MINOR; 343 344 pExa->memoryBase = fPtr->fbmem; 345 pExa->memorySize = fPtr->fbmem_len; 346 pExa->offScreenBase = fPtr->linebytes * fPtr->info.height; 347 pExa->pixmapOffsetAlign = 4; 348 pExa->pixmapPitchAlign = 4; 349 350 pExa->flags = EXA_OFFSCREEN_PIXMAPS; 351 352 pExa->maxX = 2048; 353 pExa->maxY = 2048; 354 355 pExa->MarkSync = IgsMarkSync; 356 pExa->WaitMarker = IgsWaitMarker; 357 pExa->PrepareSolid = IgsPrepareSolid; 358 pExa->Solid = IgsSolid; 359 pExa->DoneSolid = IgsDoneCopy; 360 pExa->PrepareCopy = IgsPrepareCopy; 361 pExa->Copy = IgsCopy; 362 pExa->DoneCopy = IgsDoneCopy; 363 364 switch(fPtr->info.depth) { 365 case 8: 366 fPtr->shift = 0; 367 fPtr->mapfmt = IGS_COP_MAP_8BPP; 368 break; 369 case 16: 370 fPtr->shift = 1; 371 fPtr->mapfmt = IGS_COP_MAP_16BPP; 372 break; 373 case 24: 374 case 32: 375 fPtr->shift = 2; 376 fPtr->mapfmt = IGS_COP_MAP_32BPP; 377 break; 378 default: 379 ErrorF("Unsupported depth: %d\n", fPtr->info.depth); 380 } 381 IgsWrite1(fPtr, IGS_COP_MAP_FMT_REG, fPtr->mapfmt); 382 383 /* EXA hits more optimized paths when it does not have to fallback 384 * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 385 */ 386 pExa->UploadToScreen = IgsUploadToScreen; 387 pExa->DownloadFromScreen = IgsDownloadFromScreen; 388#ifdef __arm__ 389 pExa->PrepareAccess = IgsPrepareAccess; 390 pExa->FinishAccess = IgsFinishAccess; 391#endif 392 return exaDriverInit(pScreen, pExa); 393} 394