ngle_accel.c revision 7517da51
1/* 2 * NGLE - hardware acceleration. 3 * 4 * Copyright (C) 2024 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: ngle_accel.c,v 1.6 2024/12/07 10:48:38 macallan Exp $ */ 25 26#include <sys/types.h> 27#include <dev/ic/stireg.h> 28 29 30#include "ngle.h" 31 32//#define DEBUG 33 34#ifdef DEBUG 35#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 36#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 37#define DBGMSG xf86Msg 38#else 39#define ENTER 40#define DBGMSG if (0) xf86Msg 41#define LEAVE 42#endif 43 44static void 45NGLEWaitMarker(ScreenPtr pScreen, int Marker) 46{ 47 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 48 NGLEPtr fPtr = NGLEPTR(pScrn); 49 uint8_t stat; 50 51 ENTER; 52 do { 53 stat = NGLERead1(fPtr, NGLE_REG_15b0); 54 if (stat == 0) 55 stat = NGLERead1(fPtr, NGLE_REG_15b0); 56 } while (stat != 0); 57 LEAVE; 58} 59 60static void 61NGLEWaitFifo(NGLEPtr fPtr, int slots) 62{ 63 uint32_t reg; 64 65 ENTER; 66 do { 67 reg = NGLERead4(fPtr, NGLE_REG_34); 68 } while (reg < slots); 69 LEAVE; 70} 71 72static Bool 73NGLEPrepareCopy_EG 74( 75 PixmapPtr pSrcPixmap, 76 PixmapPtr pDstPixmap, 77 int xdir, 78 int ydir, 79 int alu, 80 Pixel planemask 81) 82{ 83 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 84 NGLEPtr fPtr = NGLEPTR(pScrn); 85 int srcpitch = exaGetPixmapPitch(pSrcPixmap); 86 int srcoff = exaGetPixmapOffset(pSrcPixmap); 87 88 ENTER; 89 90 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 91 fPtr->offset = srcoff >> 11; 92 NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 93 NGLEWrite4(fPtr, NGLE_REG_10, 94 BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 95 NGLEWrite4(fPtr, NGLE_REG_14, 96 IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0)); 97 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 98 99 fPtr->hwmode = HW_BLIT; 100 101 LEAVE; 102 return TRUE; 103} 104 105static Bool 106NGLEPrepareCopy_HCRX 107( 108 PixmapPtr pSrcPixmap, 109 PixmapPtr pDstPixmap, 110 int xdir, 111 int ydir, 112 int alu, 113 Pixel planemask 114) 115{ 116 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 117 NGLEPtr fPtr = NGLEPTR(pScrn); 118 int srcpitch = exaGetPixmapPitch(pSrcPixmap); 119 int srcoff = exaGetPixmapOffset(pSrcPixmap); 120 121 ENTER; 122 123 DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 124 fPtr->offset = srcoff / srcpitch; 125 NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 126 NGLEWrite4(fPtr, NGLE_REG_10, 127 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 128 NGLEWrite4(fPtr, NGLE_REG_14, 129 IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 0, 0)); 130 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 131 132 fPtr->hwmode = HW_BLIT; 133 134 LEAVE; 135 return TRUE; 136} 137 138static void 139NGLECopy 140( 141 PixmapPtr pDstPixmap, 142 int xs, 143 int ys, 144 int xd, 145 int yd, 146 int wi, 147 int he 148) 149{ 150 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 151 NGLEPtr fPtr = NGLEPTR(pScrn); 152 int dstpitch = exaGetPixmapPitch(pDstPixmap); 153 int dstoff = exaGetPixmapOffset(pDstPixmap); 154 155 ENTER; 156 NGLEWaitFifo(fPtr, 3); 157 NGLEWrite4(fPtr, NGLE_REG_24, (xs << 16) | (ys + fPtr->offset)); 158 NGLEWrite4(fPtr, NGLE_REG_7, (wi << 16) | he); 159 NGLEWrite4(fPtr, NGLE_REG_25, (xd << 16) | (yd + (dstoff / dstpitch))); 160 161 exaMarkSync(pDstPixmap->drawable.pScreen); 162 LEAVE; 163} 164 165static void 166NGLEDoneCopy(PixmapPtr pDstPixmap) 167{ 168 ENTER; 169 LEAVE; 170} 171 172static Bool 173NGLEPrepareSolid_EG( 174 PixmapPtr pPixmap, 175 int alu, 176 Pixel planemask, 177 Pixel fg) 178{ 179 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 180 NGLEPtr fPtr = NGLEPTR(pScrn); 181 182 ENTER; 183 NGLEWaitFifo(fPtr, 4); 184 /* plane mask */ 185 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 186 /* bitmap op */ 187 NGLEWrite4(fPtr, NGLE_REG_14, 188 IBOvals(alu, 0, BitmapExtent08, 0, DataDynamic, MaskOtc, 1, 0)); 189 /* dst bitmap access */ 190 NGLEWrite4(fPtr, NGLE_REG_11, 191 BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0)); 192 NGLEWrite4(fPtr, NGLE_REG_35, fg); 193 fPtr->hwmode = HW_FILL; 194 195 LEAVE; 196 return TRUE; 197} 198 199static Bool 200NGLEPrepareSolid_HCRX( 201 PixmapPtr pPixmap, 202 int alu, 203 Pixel planemask, 204 Pixel fg) 205{ 206 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 207 NGLEPtr fPtr = NGLEPTR(pScrn); 208 209 ENTER; 210 NGLEWaitFifo(fPtr, 4); 211 /* plane mask */ 212 NGLEWrite4(fPtr, NGLE_REG_13, planemask); 213 /* bitmap op */ 214 NGLEWrite4(fPtr, NGLE_REG_14, 215 IBOvals(alu, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 1, 0)); 216 /* dst bitmap access */ 217 NGLEWrite4(fPtr, NGLE_REG_11, 218 BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 0)); 219 NGLEWrite4(fPtr, NGLE_REG_35, fg); 220 fPtr->hwmode = HW_FILL; 221 222 LEAVE; 223 return TRUE; 224} 225 226static void 227NGLESolid( 228 PixmapPtr pPixmap, 229 int x1, 230 int y1, 231 int x2, 232 int y2) 233{ 234 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 235 NGLEPtr fPtr = NGLEPTR(pScrn); 236 int w = x2 - x1, h = y2 - y1; 237 int pitch = exaGetPixmapPitch(pPixmap); 238 int offset = exaGetPixmapOffset(pPixmap); 239 uint32_t mask; 240 int wi, rest; 241 242 ENTER; 243 244 y1 += offset / pitch; 245 246 /* 247 * XXX 248 * Turns out this thing always fills rectangles to the next 32 pixel 249 * boundary on te right. To get around this we split the rectangle 250 * into a multiples-of-32 part and the rest, so we can mask off the 251 * excess pixels. 252 */ 253 rest = w & 0x1f; 254 wi = w & 0xffffe0; 255 if (wi > 0) { 256 NGLEWaitFifo(fPtr, 3); 257 /* transfer data */ 258 NGLEWrite4(fPtr, NGLE_REG_8, 0xffffffff); 259 /* dst XY */ 260 NGLEWrite4(fPtr, NGLE_REG_6, (x1 << 16) | y1); 261 /* len XY start */ 262 NGLEWrite4(fPtr, NGLE_REG_9, (wi << 16) | h); 263 } 264 if (rest > 0) { 265 mask = 0xffffffff << (32 - w); 266 /* transfer data */ 267 NGLEWaitFifo(fPtr, 3); 268 NGLEWrite4(fPtr, NGLE_REG_8, mask); 269 /* dst XY */ 270 NGLEWrite4(fPtr, NGLE_REG_6, ((x1 + wi) << 16) | y1); 271 /* len XY start */ 272 NGLEWrite4(fPtr, NGLE_REG_9, (rest << 16) | h); 273 } 274 exaMarkSync(pPixmap->drawable.pScreen); 275 LEAVE; 276} 277 278Bool 279NGLEPrepareAccess_EG(PixmapPtr pPixmap, int index) 280{ 281 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 282 NGLEPtr fPtr = NGLEPTR(pScrn); 283 284 if (fPtr->hwmode == HW_FB) return TRUE; 285 286 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 287 NGLEWrite4(fPtr, NGLE_REG_10, 288 BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 289 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 290 NGLEWrite4(fPtr, NGLE_REG_13, 0xff); 291 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 292 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 293 fPtr->hwmode = HW_FB; 294 return TRUE; 295} 296 297Bool 298NGLEPrepareAccess_HCRX(PixmapPtr pPixmap, int index) 299{ 300 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 301 NGLEPtr fPtr = NGLEPTR(pScrn); 302 303 if (fPtr->hwmode == HW_FB) return TRUE; 304 305 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 306 NGLEWrite4(fPtr, NGLE_REG_10, 307 BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 308 NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 309 NGLEWrite4(fPtr, NGLE_REG_13, 0xffffffff); 310 NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 311 NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 312 fPtr->hwmode = HW_FB; 313 return TRUE; 314} 315Bool 316NGLEInitAccel(ScreenPtr pScreen) 317{ 318 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 319 NGLEPtr fPtr = NGLEPTR(pScrn); 320 ExaDriverPtr pExa; 321 int lines, bpp = pScrn->bitsPerPixel >> 3; 322 323 pExa = exaDriverAlloc(); 324 if (!pExa) 325 return FALSE; 326 327 fPtr->pExa = pExa; 328 329 pExa->exa_major = EXA_VERSION_MAJOR; 330 pExa->exa_minor = EXA_VERSION_MINOR; 331 332 pExa->memoryBase = fPtr->fbmem; 333 lines = fPtr->fbmem_len / fPtr->fbi.fbi_stride; 334 DBGMSG(X_ERROR, "lines %d\n", lines); 335 pExa->memorySize = fPtr->fbmem_len; 336 pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 337 pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 338 pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 339 340 pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 341 342 pExa->maxX = 2048; 343 pExa->maxY = 2048; 344 345 fPtr->hwmode = -1; 346 347 pExa->WaitMarker = NGLEWaitMarker; 348 pExa->Solid = NGLESolid; 349 pExa->DoneSolid = NGLEDoneCopy; 350 pExa->Copy = NGLECopy; 351 pExa->DoneCopy = NGLEDoneCopy; 352 switch (fPtr->gid) { 353 case STI_DD_EG: 354 pExa->PrepareCopy = NGLEPrepareCopy_EG; 355 pExa->PrepareSolid = NGLEPrepareSolid_EG; 356 pExa->PrepareAccess = NGLEPrepareAccess_EG; 357 break; 358 case STI_DD_HCRX: 359 pExa->PrepareCopy = NGLEPrepareCopy_HCRX; 360 pExa->PrepareSolid = NGLEPrepareSolid_HCRX; 361 pExa->PrepareAccess = NGLEPrepareAccess_HCRX; 362 break; 363 default: 364 xf86Msg(X_ERROR, 365 "unsupported device GID %08x\n", fPtr->gid); 366 return FALSE; 367 } 368 NGLEWaitMarker(pScreen, 0); 369 370 return exaDriverInit(pScreen, pExa); 371} 372