cg6_exa.c revision 6d8d5fbf
1/* 2 * Sun GX and Turbo GX EXA support 3 * 4 * Copyright (C) 2015 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/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/suncg6/cg6_accel.c $ */ 24 25#include "cg6.h" 26#include "cg6_regs.h" 27 28 29static CARD32 Cg6BlitROP[] = { 30 ROP_BLIT(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ 31 ROP_BLIT(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ 32 ROP_BLIT(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ 33 ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ 34 ROP_BLIT(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ 35 ROP_BLIT(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ 36 ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ 37 ROP_BLIT(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ 38 ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ 39 ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ 40 ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ 41 ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ 42 ROP_BLIT(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ 43 ROP_BLIT(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ 44 ROP_BLIT(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ 45 ROP_BLIT(GX_ROP_SET, GX_ROP_SET), /* GXset */ 46}; 47 48static CARD32 Cg6DrawROP[] = { 49 ROP_FILL(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ 50 ROP_FILL(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ 51 ROP_FILL(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ 52 ROP_FILL(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ 53 ROP_FILL(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ 54 ROP_FILL(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ 55 ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ 56 ROP_FILL(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ 57 ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ 58 ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ 59 ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ 60 ROP_FILL(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ 61 ROP_FILL(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ 62 ROP_FILL(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ 63 ROP_FILL(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ 64 ROP_FILL(GX_ROP_SET, GX_ROP_SET), /* GXset */ 65}; 66 67#define runDraw(pCg6) { volatile CARD32 rubbish = pCg6->fbc->draw; } 68#define runBlit(pCg6) { volatile CARD32 rubbish = pCg6->fbc->blit; } 69 70/* 71 * XXX 72 * was GX_FULL, which apparently isn't enough on some (slower) CG6 like 73 * the one found on the SPARCstation LX mainboard 74 */ 75#define waitReady(pCg6) while(pCg6->fbc->s & GX_INPROGRESS) 76 77void Cg6InitEngine(Cg6Ptr); 78 79static void 80Cg6WaitMarker(ScreenPtr pScreen, int Marker) 81{ 82 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 83 Cg6Ptr p = GET_CG6_FROM_SCRN(pScrn); 84 85 waitReady(p); 86} 87 88static Bool 89Cg6PrepareCopy 90( 91 PixmapPtr pSrcPixmap, 92 PixmapPtr pDstPixmap, 93 int xdir, 94 int ydir, 95 int alu, 96 Pixel planemask 97) 98{ 99 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 100 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 101 102 waitReady(pCg6); 103 104 pCg6->fbc->mode = GX_BLIT_SRC | 105 GX_MODE_COLOR8 | 106 GX_DRAW_RENDER | 107 GX_BWRITE0_ENABLE | 108 GX_BWRITE1_DISABLE | 109 GX_BREAD_0 | 110 GX_BDISP_0; 111 112 /* we probably don't need the following three */ 113 pCg6->fbc->fg = 0xff; 114 pCg6->fbc->bg = 0x00; 115 pCg6->fbc->s = 0; 116 117 pCg6->srcoff = exaGetPixmapOffset(pSrcPixmap) / pCg6->width; 118 pCg6->fbc->alu = Cg6BlitROP[alu]; 119 pCg6->fbc->pm = planemask; 120 return TRUE; 121} 122 123static void 124Cg6Copy 125( 126 PixmapPtr pDstPixmap, 127 int xSrc, 128 int ySrc, 129 int xDst, 130 int yDst, 131 int w, 132 int h 133) 134{ 135 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 136 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 137 int doff; 138 139 doff = exaGetPixmapOffset(pDstPixmap) / pCg6->width; 140 waitReady(pCg6); 141 pCg6->fbc->x0 = xSrc; 142 pCg6->fbc->y0 = ySrc + pCg6->srcoff; 143 pCg6->fbc->x1 = xSrc + w - 1; 144 pCg6->fbc->y1 = ySrc + pCg6->srcoff + h - 1; 145 pCg6->fbc->x2 = xDst; 146 pCg6->fbc->y2 = yDst + doff; 147 pCg6->fbc->x3 = xDst + w - 1; 148 pCg6->fbc->y3 = yDst + doff + h - 1; 149 runBlit(pCg6); 150 exaMarkSync(pDstPixmap->drawable.pScreen); 151} 152 153static void 154Cg6DoneCopy(PixmapPtr pDstPixmap) 155{ 156 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 157 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 158 159 waitReady(pCg6); 160} 161 162static Bool 163Cg6PrepareSolid( 164 PixmapPtr pPixmap, 165 int alu, 166 Pixel planemask, 167 Pixel fg) 168{ 169 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 170 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 171 CARD32 c2; 172 173 pCg6->srcoff = exaGetPixmapOffset(pPixmap) / pCg6->width; 174 175 waitReady(pCg6); 176 177 pCg6->fbc->mode = GX_BLIT_SRC | 178 GX_MODE_COLOR8 | 179 GX_DRAW_RENDER | 180 GX_BWRITE0_ENABLE | 181 GX_BWRITE1_DISABLE | 182 GX_BREAD_0 | 183 GX_BDISP_0; 184 pCg6->fbc->fg = fg; 185 pCg6->fbc->s = 0; 186 pCg6->fbc->alu = Cg6DrawROP[alu]; 187 pCg6->fbc->pm = planemask; 188 return TRUE; 189} 190 191static void 192Cg6Solid( 193 PixmapPtr pPixmap, 194 int x, 195 int y, 196 int x2, 197 int y2) 198{ 199 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 200 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 201 202 waitReady(pCg6); 203 pCg6->fbc->arecty = y + pCg6->srcoff; 204 pCg6->fbc->arectx = x; 205 pCg6->fbc->rrecty = y2 - y - 1; 206 pCg6->fbc->rrectx = x2 - x - 1; 207 runDraw(pCg6); 208 exaMarkSync(pPixmap->drawable.pScreen); 209} 210 211/* 212 * Memcpy-based UTS. 213 * TODO: use host blit 214 */ 215static Bool 216Cg6UploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 217 char *src, int src_pitch) 218{ 219 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 220 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 221 uint32_t *sline; 222 int dst_pitch = exaGetPixmapPitch(pDst); 223 int dst_line = y + exaGetPixmapOffset(pDst) / pCg6->width; 224 int i, bits; 225 int words = (w + 3) >> 2; 226 227 /* clip to the destination */ 228 pCg6->fbc->clipmaxx = x + w - 1; 229 pCg6->fbc->clipminx = x; 230 231 /* see if the source is aligned, if not adjust */ 232 bits = ((long)src) & 3; 233 if (bits != 0) { 234 src -= bits; 235 w += bits; 236 words = (w + 3) >> 2; 237 x -= bits; 238 } 239 240 /* we assume that source pitch is always a multiple of 4 */ 241 if ((src_pitch & 3) != 0) 242 xf86Msg(X_ERROR, "pitch %d\n", src_pitch); 243 waitReady(pCg6); 244 245 pCg6->fbc->mode = GX_BLIT_NOSRC | 246 GX_MODE_COLOR8 | 247 GX_DRAW_RENDER | 248 GX_BWRITE0_ENABLE | 249 GX_BWRITE1_DISABLE | 250 GX_BREAD_0 | 251 GX_BDISP_0; 252 253 pCg6->fbc->alu = Cg6BlitROP[GXcopy]; 254 pCg6->fbc->pm = 0xffffffff; 255 pCg6->fbc->incx = 4; 256 pCg6->fbc->incy = 0; 257 while (h--) { 258 pCg6->fbc->x0 = x; 259 pCg6->fbc->x1 = x + 3; 260 pCg6->fbc->y0 = dst_line; 261 sline = (uint32_t *)src; 262 for (i = 0; i < words; i++) { 263 pCg6->fbc->font = *sline; 264 sline++; 265 } 266 src += src_pitch; 267 dst_line++; 268 } 269 pCg6->fbc->clipmaxx = 4096; 270 pCg6->fbc->clipminx = 0; 271 exaMarkSync(pDst->drawable.pScreen); 272 return TRUE; 273} 274 275/* 276 * Memcpy-based DFS. 277 */ 278static Bool 279Cg6DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 280 char *dst, int dst_pitch) 281{ 282 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 283 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 284 char *src = pCg6->fb + exaGetPixmapOffset(pSrc); 285 int src_pitch = exaGetPixmapPitch(pSrc); 286 287 src += x + (y * src_pitch); 288 289 while (h > 0) { 290 memcpy(dst, src, w); 291 src += src_pitch; 292 dst += dst_pitch; 293 h--; 294 } 295 return TRUE; 296} 297 298int 299CG6EXAInit(ScreenPtr pScreen) 300{ 301 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 302 Cg6Ptr pCg6 = GET_CG6_FROM_SCRN(pScrn); 303 ExaDriverPtr pExa; 304 305 Cg6InitEngine(pCg6); 306 307 pExa = exaDriverAlloc(); 308 if (!pExa) 309 return FALSE; 310 311 pCg6->pExa = pExa; 312 313 pExa->exa_major = EXA_VERSION_MAJOR; 314 pExa->exa_minor = EXA_VERSION_MINOR; 315 316 pExa->memoryBase = pCg6->fb; 317 318 /* round to multiple of pixmap pitch */ 319 pExa->memorySize = (pCg6->vidmem / pCg6->width) * pCg6->width; 320 pExa->offScreenBase = pCg6->width * pCg6->height; 321 322 /* 323 * our blitter can't deal with variable pitches 324 */ 325 pExa->pixmapOffsetAlign = pCg6->width; 326 pExa->pixmapPitchAlign = pCg6->width; 327 328 pExa->flags = EXA_OFFSCREEN_PIXMAPS | 329 EXA_MIXED_PIXMAPS; 330 331 pExa->maxX = 4096; 332 pExa->maxY = 4096; 333 334 pExa->WaitMarker = Cg6WaitMarker; 335 336 pExa->PrepareSolid = Cg6PrepareSolid; 337 pExa->Solid = Cg6Solid; 338 pExa->DoneSolid = Cg6DoneCopy; 339 340 pExa->PrepareCopy = Cg6PrepareCopy; 341 pExa->Copy = Cg6Copy; 342 pExa->DoneCopy = Cg6DoneCopy; 343 344 pExa->UploadToScreen = Cg6UploadToScreen; 345 pExa->DownloadFromScreen = Cg6DownloadFromScreen; 346 347 return exaDriverInit(pScreen, pExa);; 348} 349