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