nv_exa.c revision 2d0d2c2b
1/* 2 * crude EXA support for geforce chips 3 * 4 * Copyright (C) 2018 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: nv_exa.c,v 1.3 2018/07/16 16:30:04 macallan Exp $ */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include "nv_include.h" 31#include "miline.h" 32#include "nv_dma.h" 33#include "exa.h" 34 35//#define DEBUG 36 37#ifdef DEBUG 38#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 39#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 40#else 41#define ENTER 42#define LEAVE 43#endif 44 45static void 46NvWaitMarker(ScreenPtr pScreen, int Marker) 47{ 48 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 49 50 ENTER; 51 NVSync(pScrn); 52 LEAVE; 53} 54 55static Bool 56NvPrepareCopy 57( 58 PixmapPtr pSrcPixmap, 59 PixmapPtr pDstPixmap, 60 int xdir, 61 int ydir, 62 int rop, 63 Pixel planemask 64) 65{ 66 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 67 NVPtr pNv = NVPTR(pScrn); 68 int srcpitch, srcoff, dstpitch, dstoff; 69 70 ENTER; 71 if (pSrcPixmap->drawable.bitsPerPixel != 32) 72 xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pSrcPixmap->drawable.bitsPerPixel); 73 planemask |= ~0 << pNv->CurrentLayout.depth; 74 NVSetRopSolid(pScrn, rop, planemask); 75 pNv->DMAKickoffCallback = NVDMAKickoffCallback; 76 dstpitch = exaGetPixmapPitch(pDstPixmap); 77 dstoff = exaGetPixmapOffset(pDstPixmap); 78 srcpitch = exaGetPixmapPitch(pSrcPixmap); 79 srcoff = exaGetPixmapOffset(pSrcPixmap); 80 81 NVDmaStart(pNv, SURFACE_PITCH, 3); 82 NVDmaNext (pNv, srcpitch | (dstpitch << 16)); 83 NVDmaNext (pNv, srcoff); 84 NVDmaNext (pNv, dstoff); 85 86 LEAVE; 87 return TRUE; 88} 89 90static void 91NvCopy 92( 93 PixmapPtr pDstPixmap, 94 int srcX, 95 int srcY, 96 int dstX, 97 int dstY, 98 int w, 99 int h 100) 101{ 102 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 103 NVPtr pNv = NVPTR(pScrn); 104 105 NVDmaStart(pNv, BLIT_POINT_SRC, 3); 106 NVDmaNext (pNv, (srcY << 16) | srcX); 107 NVDmaNext (pNv, (dstY << 16) | dstX); 108 NVDmaNext (pNv, (h << 16) | w); 109 110 if((w * h) >= 512) 111 NVDmaKickoff(pNv); 112 113 LEAVE; 114} 115 116static void 117NvDoneCopy(PixmapPtr pDstPixmap) 118{ 119 ENTER; 120 LEAVE; 121} 122 123static Bool 124NvPrepareSolid( 125 PixmapPtr pPixmap, 126 int rop, 127 Pixel planemask, 128 Pixel color) 129{ 130 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 131 NVPtr pNv = NVPTR(pScrn); 132 int pitch, off; 133 134 ENTER; 135 if (pPixmap->drawable.bitsPerPixel != 32) 136 xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pPixmap->drawable.bitsPerPixel); 137 planemask |= ~0 << pNv->CurrentLayout.depth; 138 139 140 pitch = exaGetPixmapPitch(pPixmap); 141 off = exaGetPixmapOffset(pPixmap); 142 143 NVDmaStart(pNv, SURFACE_PITCH, 3); 144 NVDmaNext (pNv, pitch | (pitch << 16)); 145 NVDmaNext (pNv, off); 146 NVDmaNext (pNv, off); 147 148 NVSetRopSolid(pScrn, rop, planemask); 149 pNv->DMAKickoffCallback = NVDMAKickoffCallback; 150 NVDmaStart(pNv, RECT_SOLID_COLOR, 1); 151 NVDmaNext (pNv, color); 152 153 LEAVE; 154 return TRUE; 155} 156 157static void 158NvSolid( 159 PixmapPtr pPixmap, 160 int x1, 161 int y1, 162 int x2, 163 int y2) 164{ 165 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 166 NVPtr pNv = NVPTR(pScrn); 167 int w = x2 - x1, h = y2 - y1; 168 169 ENTER; 170 NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2); 171 NVDmaNext (pNv, (x1 << 16) | y1); 172 NVDmaNext (pNv, (w << 16) | h); 173 174 if((w * h) >= 512) 175 NVDmaKickoff(pNv); 176 177 LEAVE; 178} 179 180/* 181 * Memcpy-based UTS. 182 */ 183static Bool 184NvUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 185 char *src, int src_pitch) 186{ 187 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 188 NVPtr pNv = NVPTR(pScrn); 189 unsigned char *dst = pNv->FbStart + exaGetPixmapOffset(pDst); 190 int dst_pitch = exaGetPixmapPitch(pDst); 191 192 int bpp = pDst->drawable.bitsPerPixel; 193 int cpp = (bpp + 7) >> 3; 194 int wBytes = w * cpp; 195 196 ENTER; 197 dst += (x * cpp) + (y * dst_pitch); 198 199 NVSync(pScrn); 200 201 while (h--) { 202 memcpy(dst, src, wBytes); 203 src += src_pitch; 204 dst += dst_pitch; 205 } 206 _NV_FENCE() 207 LEAVE; 208 return TRUE; 209} 210 211/* 212 * Memcpy-based DFS. 213 */ 214static Bool 215NvDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 216 char *dst, int dst_pitch) 217{ 218 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 219 NVPtr pNv = NVPTR(pScrn); 220 unsigned char *src = pNv->FbStart + exaGetPixmapOffset(pSrc); 221 int src_pitch = exaGetPixmapPitch(pSrc); 222 223 int bpp = pSrc->drawable.bitsPerPixel; 224 int cpp = (bpp + 7) >> 3; 225 int wBytes = w * cpp; 226 227 ENTER; 228 src += (x * cpp) + (y * src_pitch); 229 230 NVSync(pScrn); 231 232 while (h--) { 233 memcpy(dst, src, wBytes); 234 src += src_pitch; 235 dst += dst_pitch; 236 } 237 LEAVE; 238 return TRUE; 239} 240 241static Bool 242NvPrepareAccess(PixmapPtr pPix, int index) 243{ 244 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 245 246 NVSync(pScrn); 247 return TRUE; 248} 249 250static void 251NvFinishAccess(PixmapPtr pPix, int index) 252{ 253} 254 255Bool 256NvInitExa(ScreenPtr pScreen) 257{ 258 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 259 NVPtr pNv = NVPTR(pScrn); 260 ExaDriverPtr pExa; 261 int surfaceFormat, rectFormat; 262 263 pExa = exaDriverAlloc(); 264 if (!pExa) 265 return FALSE; 266 267 pNv->pExa = pExa; 268 269 NVResetGraphics(pScrn); 270 271 pExa->exa_major = EXA_VERSION_MAJOR; 272 pExa->exa_minor = EXA_VERSION_MINOR; 273 274 pExa->memoryBase = pNv->FbStart; 275 pExa->memorySize = pNv->ScratchBufferStart & (~63); 276 pExa->offScreenBase = pScrn->virtualY * 277 pScrn->displayWidth * pScrn->bitsPerPixel >> 3; 278 pExa->pixmapOffsetAlign = 64; 279 pExa->pixmapPitchAlign = 64; 280 281 pExa->flags = EXA_OFFSCREEN_PIXMAPS | 282 EXA_SUPPORTS_OFFSCREEN_OVERLAPS | 283 EXA_MIXED_PIXMAPS; 284 285 pExa->maxX = 8192; 286 pExa->maxY = 8192; 287 288 pExa->WaitMarker = NvWaitMarker; 289 pExa->PrepareSolid = NvPrepareSolid; 290 pExa->Solid = NvSolid; 291 pExa->DoneSolid = NvDoneCopy; 292 pExa->PrepareCopy = NvPrepareCopy; 293 pExa->Copy = NvCopy; 294 pExa->DoneCopy = NvDoneCopy; 295 296 switch(pNv->CurrentLayout.depth) { 297 case 24: 298 surfaceFormat = SURFACE_FORMAT_DEPTH24; 299 rectFormat = RECT_FORMAT_DEPTH24; 300 break; 301 case 16: 302 case 15: 303 surfaceFormat = SURFACE_FORMAT_DEPTH16; 304 rectFormat = RECT_FORMAT_DEPTH16; 305 break; 306 default: 307 surfaceFormat = SURFACE_FORMAT_DEPTH8; 308 rectFormat = RECT_FORMAT_DEPTH8; 309 break; 310 } 311 NVDmaStart(pNv, SURFACE_FORMAT, 1); 312 NVDmaNext (pNv, surfaceFormat); 313 NVDmaStart(pNv, RECT_FORMAT, 1); 314 NVDmaNext (pNv, rectFormat); 315 316 pNv->currentRop = ~0; /* set to something invalid */ 317 NVSetRopSolid(pScrn, GXcopy, ~0); 318 319 NVDmaKickoff(pNv); 320 321 /* EXA hits more optimized paths when it does not have to fallback 322 * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 323 */ 324 pExa->UploadToScreen = NvUploadToScreen; 325 pExa->DownloadFromScreen = NvDownloadFromScreen; 326 pExa->PrepareAccess = NvPrepareAccess; 327 pExa->FinishAccess = NvFinishAccess; 328 329 return exaDriverInit(pScreen, pExa); 330} 331