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