igs_accel.c revision 9a5ed1c5
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.2 2009/11/21 22:22:27 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->info.depth >> 3) - 1); 75 while ((IgsRead1(fPtr, 76 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ) != 0) 77 && (bail > 0)) { 78 bail--; 79 usleep(1); 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->info.depth >> 3) - 1); 104 while (((IgsRead1(fPtr, 105 IGS_COP_CTL_REG) & (IGS_COP_CTL_BUSY | IGS_COP_CTL_HFEMPTZ)) != 0) 106 && (bail > 0)) { 107 bail--; 108 usleep(1); 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) / 8; 265 int wBytes = w * cpp; 266 267 ENTER; 268 dst += (x * cpp) + (y * dst_pitch); 269 270 while (h--) { 271 memcpy(dst, src, wBytes); 272 src += src_pitch; 273 dst += dst_pitch; 274 } 275 LEAVE; 276 return TRUE; 277} 278 279/* 280 * Memcpy-based DFS. 281 */ 282static Bool 283IgsDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 284 char *dst, int dst_pitch) 285{ 286 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 287 IgsPtr fPtr = IGSPTR(pScrn); 288 char *src = fPtr->fbmem + exaGetPixmapOffset(pSrc); 289 int src_pitch = exaGetPixmapPitch(pSrc); 290 291 int bpp = pSrc->drawable.bitsPerPixel; 292 int cpp = (bpp + 7) / 8; 293 int wBytes = w * cpp; 294 295 ENTER; 296 src += (x * cpp) + (y * src_pitch); 297 298 while (h--) { 299 memcpy(dst, src, wBytes); 300 src += src_pitch; 301 dst += dst_pitch; 302 } 303 LEAVE; 304 return TRUE; 305} 306 307Bool 308IgsInitAccel(ScreenPtr pScreen) 309{ 310 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 311 IgsPtr fPtr = IGSPTR(pScrn); 312 ExaDriverPtr pExa; 313 314 pExa = exaDriverAlloc(); 315 if (!pExa) 316 return FALSE; 317 318 fPtr->pExa = pExa; 319 320 pExa->exa_major = EXA_VERSION_MAJOR; 321 pExa->exa_minor = EXA_VERSION_MINOR; 322 323 pExa->memoryBase = fPtr->fbmem; 324 pExa->memorySize = fPtr->fbmem_len; 325 pExa->offScreenBase = fPtr->linebytes * fPtr->info.height; 326 pExa->pixmapOffsetAlign = 4; 327 pExa->pixmapPitchAlign = 4; 328 329 pExa->flags = EXA_OFFSCREEN_PIXMAPS; 330 331 pExa->maxX = 2048; 332 pExa->maxY = 2048; 333 334 pExa->MarkSync = IgsMarkSync; 335 pExa->WaitMarker = IgsWaitMarker; 336 pExa->PrepareSolid = IgsPrepareSolid; 337 pExa->Solid = IgsSolid; 338 pExa->DoneSolid = IgsDoneCopy; 339 pExa->PrepareCopy = IgsPrepareCopy; 340 pExa->Copy = IgsCopy; 341 pExa->DoneCopy = IgsDoneCopy; 342 343 switch(fPtr->info.depth) { 344 case 8: 345 fPtr->shift = 0; 346 break; 347 case 16: 348 fPtr->shift = 1; 349 break; 350 case 32: 351 fPtr->shift = 2; 352 break; 353 } 354 /* EXA hits more optimized paths when it does not have to fallback 355 * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 356 */ 357 pExa->UploadToScreen = IgsUploadToScreen; 358 pExa->DownloadFromScreen = IgsDownloadFromScreen; 359 360 return exaDriverInit(pScreen, pExa); 361} 362