1727c6de2Smacallan/* 2727c6de2Smacallan * NGLE - hardware acceleration. 3727c6de2Smacallan * 4727c6de2Smacallan * Copyright (C) 2024 Michael Lorenz 5727c6de2Smacallan * 6727c6de2Smacallan * Permission is hereby granted, free of charge, to any person obtaining a copy 7727c6de2Smacallan * of this software and associated documentation files (the "Software"), to deal 8727c6de2Smacallan * in the Software without restriction, including without limitation the rights 9727c6de2Smacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10727c6de2Smacallan * copies of the Software, and to permit persons to whom the Software is 11727c6de2Smacallan * furnished to do so, subject to the following conditions: 12727c6de2Smacallan * 13727c6de2Smacallan * The above copyright notice and this permission notice shall be included in 14727c6de2Smacallan * all copies or substantial portions of the Software. 15727c6de2Smacallan * 16727c6de2Smacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17727c6de2Smacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18727c6de2Smacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19727c6de2Smacallan * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20727c6de2Smacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21727c6de2Smacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22727c6de2Smacallan */ 23727c6de2Smacallan 24e4f83f77Smacallan/* $NetBSD: ngle_accel.c,v 1.7 2025/03/05 07:22:24 macallan Exp $ */ 25727c6de2Smacallan 26727c6de2Smacallan#include <sys/types.h> 27727c6de2Smacallan#include <dev/ic/stireg.h> 28727c6de2Smacallan 29727c6de2Smacallan 30727c6de2Smacallan#include "ngle.h" 31727c6de2Smacallan 32727c6de2Smacallan//#define DEBUG 33727c6de2Smacallan 34727c6de2Smacallan#ifdef DEBUG 35727c6de2Smacallan#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 36727c6de2Smacallan#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 37727c6de2Smacallan#define DBGMSG xf86Msg 38727c6de2Smacallan#else 39727c6de2Smacallan#define ENTER 40727c6de2Smacallan#define DBGMSG if (0) xf86Msg 41727c6de2Smacallan#define LEAVE 42727c6de2Smacallan#endif 43727c6de2Smacallan 44727c6de2Smacallanstatic void 45727c6de2SmacallanNGLEWaitMarker(ScreenPtr pScreen, int Marker) 46727c6de2Smacallan{ 47727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 48727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 49727c6de2Smacallan uint8_t stat; 50727c6de2Smacallan 51727c6de2Smacallan ENTER; 52727c6de2Smacallan do { 53727c6de2Smacallan stat = NGLERead1(fPtr, NGLE_REG_15b0); 54727c6de2Smacallan if (stat == 0) 55727c6de2Smacallan stat = NGLERead1(fPtr, NGLE_REG_15b0); 56727c6de2Smacallan } while (stat != 0); 57727c6de2Smacallan LEAVE; 58727c6de2Smacallan} 59727c6de2Smacallan 60727c6de2Smacallanstatic void 61727c6de2SmacallanNGLEWaitFifo(NGLEPtr fPtr, int slots) 62727c6de2Smacallan{ 63727c6de2Smacallan uint32_t reg; 64727c6de2Smacallan 65727c6de2Smacallan ENTER; 66727c6de2Smacallan do { 67727c6de2Smacallan reg = NGLERead4(fPtr, NGLE_REG_34); 68727c6de2Smacallan } while (reg < slots); 69727c6de2Smacallan LEAVE; 70727c6de2Smacallan} 71727c6de2Smacallan 72727c6de2Smacallanstatic Bool 73ce159321SmacallanNGLEPrepareCopy_EG 74727c6de2Smacallan( 75727c6de2Smacallan PixmapPtr pSrcPixmap, 76727c6de2Smacallan PixmapPtr pDstPixmap, 77727c6de2Smacallan int xdir, 78727c6de2Smacallan int ydir, 79727c6de2Smacallan int alu, 80727c6de2Smacallan Pixel planemask 81727c6de2Smacallan) 82727c6de2Smacallan{ 83727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 84727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 85727c6de2Smacallan int srcpitch = exaGetPixmapPitch(pSrcPixmap); 86727c6de2Smacallan int srcoff = exaGetPixmapOffset(pSrcPixmap); 87727c6de2Smacallan 88727c6de2Smacallan ENTER; 89727c6de2Smacallan 90727c6de2Smacallan DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 919f844d85Smacallan fPtr->offset = srcoff >> 11; 92727c6de2Smacallan NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 93727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_10, 94727c6de2Smacallan BA(IndexedDcd, Otc04, Ots08, AddrLong, 0, BINapp0I, 0)); 959f844d85Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 96852b373fSmacallan IBOvals(RopSrc, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 0, 0)); 97727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_13, planemask); 98727c6de2Smacallan 99727c6de2Smacallan fPtr->hwmode = HW_BLIT; 100727c6de2Smacallan 101727c6de2Smacallan LEAVE; 102727c6de2Smacallan return TRUE; 103727c6de2Smacallan} 104727c6de2Smacallan 105ce159321Smacallanstatic Bool 106ce159321SmacallanNGLEPrepareCopy_HCRX 107ce159321Smacallan( 108ce159321Smacallan PixmapPtr pSrcPixmap, 109ce159321Smacallan PixmapPtr pDstPixmap, 110ce159321Smacallan int xdir, 111ce159321Smacallan int ydir, 112ce159321Smacallan int alu, 113ce159321Smacallan Pixel planemask 114ce159321Smacallan) 115ce159321Smacallan{ 116ce159321Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 117ce159321Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 118ce159321Smacallan int srcpitch = exaGetPixmapPitch(pSrcPixmap); 119ce159321Smacallan int srcoff = exaGetPixmapOffset(pSrcPixmap); 120ce159321Smacallan 121ce159321Smacallan ENTER; 122ce159321Smacallan 123ce159321Smacallan DBGMSG(X_ERROR, "%s %d %d\n", __func__, srcoff, srcpitch); 124ce159321Smacallan fPtr->offset = srcoff / srcpitch; 125ce159321Smacallan NGLEWaitMarker(pDstPixmap->drawable.pScreen, 0); 126ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_10, 127ce159321Smacallan BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 1289f844d85Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 1299f844d85Smacallan IBOvals(RopSrc, 0, BitmapExtent32, 0, DataDynamic, MaskOtc, 0, 0)); 130ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_13, planemask); 131ce159321Smacallan 132ce159321Smacallan fPtr->hwmode = HW_BLIT; 133ce159321Smacallan 134ce159321Smacallan LEAVE; 135ce159321Smacallan return TRUE; 136ce159321Smacallan} 137ce159321Smacallan 138727c6de2Smacallanstatic void 139727c6de2SmacallanNGLECopy 140727c6de2Smacallan( 141727c6de2Smacallan PixmapPtr pDstPixmap, 142727c6de2Smacallan int xs, 143727c6de2Smacallan int ys, 144727c6de2Smacallan int xd, 145727c6de2Smacallan int yd, 146727c6de2Smacallan int wi, 147727c6de2Smacallan int he 148727c6de2Smacallan) 149727c6de2Smacallan{ 150727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 151727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 152727c6de2Smacallan int dstpitch = exaGetPixmapPitch(pDstPixmap); 153727c6de2Smacallan int dstoff = exaGetPixmapOffset(pDstPixmap); 154727c6de2Smacallan 155727c6de2Smacallan ENTER; 156727c6de2Smacallan NGLEWaitFifo(fPtr, 3); 157727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_24, (xs << 16) | (ys + fPtr->offset)); 158727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_7, (wi << 16) | he); 159727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_25, (xd << 16) | (yd + (dstoff / dstpitch))); 160727c6de2Smacallan 161727c6de2Smacallan exaMarkSync(pDstPixmap->drawable.pScreen); 162727c6de2Smacallan LEAVE; 163727c6de2Smacallan} 164727c6de2Smacallan 165727c6de2Smacallanstatic void 166727c6de2SmacallanNGLEDoneCopy(PixmapPtr pDstPixmap) 167727c6de2Smacallan{ 168727c6de2Smacallan ENTER; 169727c6de2Smacallan LEAVE; 170727c6de2Smacallan} 171727c6de2Smacallan 172727c6de2Smacallanstatic Bool 173ce159321SmacallanNGLEPrepareSolid_EG( 174727c6de2Smacallan PixmapPtr pPixmap, 175727c6de2Smacallan int alu, 176727c6de2Smacallan Pixel planemask, 177727c6de2Smacallan Pixel fg) 178727c6de2Smacallan{ 179727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 180727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 181727c6de2Smacallan 182727c6de2Smacallan ENTER; 183727c6de2Smacallan NGLEWaitFifo(fPtr, 4); 184727c6de2Smacallan /* plane mask */ 185727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_13, planemask); 186727c6de2Smacallan /* bitmap op */ 187727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 188e4f83f77Smacallan IBOvals(alu, 0, BitmapExtent08, 1, DataDynamic, MaskOtc, 1, 0)); 189727c6de2Smacallan /* dst bitmap access */ 190727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_11, 191727c6de2Smacallan BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0I, 0)); 192727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_35, fg); 193727c6de2Smacallan fPtr->hwmode = HW_FILL; 194727c6de2Smacallan 195727c6de2Smacallan LEAVE; 196727c6de2Smacallan return TRUE; 197727c6de2Smacallan} 198727c6de2Smacallan 199ce159321Smacallanstatic Bool 200ce159321SmacallanNGLEPrepareSolid_HCRX( 201ce159321Smacallan PixmapPtr pPixmap, 202ce159321Smacallan int alu, 203ce159321Smacallan Pixel planemask, 204ce159321Smacallan Pixel fg) 205ce159321Smacallan{ 206ce159321Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 207ce159321Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 208ce159321Smacallan 209ce159321Smacallan ENTER; 210ce159321Smacallan NGLEWaitFifo(fPtr, 4); 211ce159321Smacallan /* plane mask */ 212ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_13, planemask); 213ce159321Smacallan /* bitmap op */ 214ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 215e4f83f77Smacallan IBOvals(alu, 0, BitmapExtent32, 1, DataDynamic, MaskOtc, 1, 0)); 216ce159321Smacallan /* dst bitmap access */ 217ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_11, 218ce159321Smacallan BA(FractDcd, Otc32, OtsIndirect, AddrLong, 0, BINapp0F8, 0)); 219ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_35, fg); 220ce159321Smacallan fPtr->hwmode = HW_FILL; 221ce159321Smacallan 222ce159321Smacallan LEAVE; 223ce159321Smacallan return TRUE; 224ce159321Smacallan} 225ce159321Smacallan 226727c6de2Smacallanstatic void 227727c6de2SmacallanNGLESolid( 228727c6de2Smacallan PixmapPtr pPixmap, 229727c6de2Smacallan int x1, 230727c6de2Smacallan int y1, 231727c6de2Smacallan int x2, 232727c6de2Smacallan int y2) 233727c6de2Smacallan{ 234727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 235727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 236727c6de2Smacallan int w = x2 - x1, h = y2 - y1; 237727c6de2Smacallan int pitch = exaGetPixmapPitch(pPixmap); 238727c6de2Smacallan int offset = exaGetPixmapOffset(pPixmap); 239727c6de2Smacallan uint32_t mask; 240727c6de2Smacallan int wi, rest; 241727c6de2Smacallan 242727c6de2Smacallan ENTER; 243727c6de2Smacallan 244852b373fSmacallan y1 += offset / pitch; 245727c6de2Smacallan 246e4f83f77Smacallan NGLEWaitFifo(fPtr, 3); 247e4f83f77Smacallan /* transfer data */ 248e4f83f77Smacallan NGLEWrite4(fPtr, NGLE_REG_8, 0xffffffff); 249e4f83f77Smacallan /* dst XY */ 250e4f83f77Smacallan NGLEWrite4(fPtr, NGLE_REG_6, (x1 << 16) | y1); 251e4f83f77Smacallan /* len XY start */ 252e4f83f77Smacallan NGLEWrite4(fPtr, NGLE_REG_9, (w << 16) | h); 253e4f83f77Smacallan 254727c6de2Smacallan exaMarkSync(pPixmap->drawable.pScreen); 255727c6de2Smacallan LEAVE; 256727c6de2Smacallan} 257727c6de2Smacallan 258727c6de2SmacallanBool 259ce159321SmacallanNGLEPrepareAccess_EG(PixmapPtr pPixmap, int index) 260727c6de2Smacallan{ 261727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 262727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 263727c6de2Smacallan 264727c6de2Smacallan if (fPtr->hwmode == HW_FB) return TRUE; 265727c6de2Smacallan 266727c6de2Smacallan NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 267ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_10, 268ce159321Smacallan BA(IndexedDcd, Otc04, Ots08, AddrByte, 0, BINapp0I, 0)); 269727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 270727c6de2Smacallan NGLEWrite4(fPtr, NGLE_REG_13, 0xff); 271727c6de2Smacallan NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 272727c6de2Smacallan NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 273727c6de2Smacallan fPtr->hwmode = HW_FB; 274727c6de2Smacallan return TRUE; 275727c6de2Smacallan} 276727c6de2Smacallan 277ce159321SmacallanBool 278ce159321SmacallanNGLEPrepareAccess_HCRX(PixmapPtr pPixmap, int index) 279ce159321Smacallan{ 280ce159321Smacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 281ce159321Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 282ce159321Smacallan 283ce159321Smacallan if (fPtr->hwmode == HW_FB) return TRUE; 284ce159321Smacallan 285ce159321Smacallan NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 286ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_10, 287ce159321Smacallan BA(FractDcd, Otc24, Ots08, AddrLong, 0, BINapp0F8, 0)); 288ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_14, 0x83000300); 289ce159321Smacallan NGLEWrite4(fPtr, NGLE_REG_13, 0xffffffff); 290ce159321Smacallan NGLEWaitMarker(pPixmap->drawable.pScreen, 0); 291ce159321Smacallan NGLEWrite1(fPtr, NGLE_REG_16b1, 1); 292ce159321Smacallan fPtr->hwmode = HW_FB; 293ce159321Smacallan return TRUE; 294ce159321Smacallan} 295727c6de2SmacallanBool 296727c6de2SmacallanNGLEInitAccel(ScreenPtr pScreen) 297727c6de2Smacallan{ 298727c6de2Smacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 299727c6de2Smacallan NGLEPtr fPtr = NGLEPTR(pScrn); 300727c6de2Smacallan ExaDriverPtr pExa; 301727c6de2Smacallan int lines, bpp = pScrn->bitsPerPixel >> 3; 302727c6de2Smacallan 303727c6de2Smacallan pExa = exaDriverAlloc(); 304727c6de2Smacallan if (!pExa) 305727c6de2Smacallan return FALSE; 306727c6de2Smacallan 307727c6de2Smacallan fPtr->pExa = pExa; 308727c6de2Smacallan 309727c6de2Smacallan pExa->exa_major = EXA_VERSION_MAJOR; 310727c6de2Smacallan pExa->exa_minor = EXA_VERSION_MINOR; 311727c6de2Smacallan 312727c6de2Smacallan pExa->memoryBase = fPtr->fbmem; 313727c6de2Smacallan lines = fPtr->fbmem_len / fPtr->fbi.fbi_stride; 314727c6de2Smacallan DBGMSG(X_ERROR, "lines %d\n", lines); 315727c6de2Smacallan pExa->memorySize = fPtr->fbmem_len; 316727c6de2Smacallan pExa->offScreenBase = fPtr->fbi.fbi_stride * fPtr->fbi.fbi_height; 317727c6de2Smacallan pExa->pixmapOffsetAlign = fPtr->fbi.fbi_stride; 318727c6de2Smacallan pExa->pixmapPitchAlign = fPtr->fbi.fbi_stride; 319727c6de2Smacallan 320727c6de2Smacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_MIXED_PIXMAPS; 321727c6de2Smacallan 322727c6de2Smacallan pExa->maxX = 2048; 323727c6de2Smacallan pExa->maxY = 2048; 324727c6de2Smacallan 325727c6de2Smacallan fPtr->hwmode = -1; 326727c6de2Smacallan 327727c6de2Smacallan pExa->WaitMarker = NGLEWaitMarker; 328727c6de2Smacallan pExa->Solid = NGLESolid; 329727c6de2Smacallan pExa->DoneSolid = NGLEDoneCopy; 330727c6de2Smacallan pExa->Copy = NGLECopy; 331727c6de2Smacallan pExa->DoneCopy = NGLEDoneCopy; 332ce159321Smacallan switch (fPtr->gid) { 333ce159321Smacallan case STI_DD_EG: 334ce159321Smacallan pExa->PrepareCopy = NGLEPrepareCopy_EG; 335ce159321Smacallan pExa->PrepareSolid = NGLEPrepareSolid_EG; 336ce159321Smacallan pExa->PrepareAccess = NGLEPrepareAccess_EG; 337ce159321Smacallan break; 338ce159321Smacallan case STI_DD_HCRX: 339ce159321Smacallan pExa->PrepareCopy = NGLEPrepareCopy_HCRX; 340ce159321Smacallan pExa->PrepareSolid = NGLEPrepareSolid_HCRX; 341ce159321Smacallan pExa->PrepareAccess = NGLEPrepareAccess_HCRX; 342ce159321Smacallan break; 343ce159321Smacallan default: 344ce159321Smacallan xf86Msg(X_ERROR, 345852b373fSmacallan "unsupported device GID %08x\n", fPtr->gid); 346ce159321Smacallan return FALSE; 347ce159321Smacallan } 348727c6de2Smacallan NGLEWaitMarker(pScreen, 0); 349727c6de2Smacallan 350727c6de2Smacallan return exaDriverInit(pScreen, pExa); 351727c6de2Smacallan} 352