nv_exa.c revision 2d0d2c2b
105c1003fSmacallan/* 205c1003fSmacallan * crude EXA support for geforce chips 305c1003fSmacallan * 405c1003fSmacallan * Copyright (C) 2018 Michael Lorenz 505c1003fSmacallan * 605c1003fSmacallan * Permission is hereby granted, free of charge, to any person obtaining a copy 705c1003fSmacallan * of this software and associated documentation files (the "Software"), to deal 805c1003fSmacallan * in the Software without restriction, including without limitation the rights 905c1003fSmacallan * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 1005c1003fSmacallan * copies of the Software, and to permit persons to whom the Software is 1105c1003fSmacallan * furnished to do so, subject to the following conditions: 1205c1003fSmacallan * 1305c1003fSmacallan * The above copyright notice and this permission notice shall be included in 1405c1003fSmacallan * all copies or substantial portions of the Software. 1505c1003fSmacallan * 1605c1003fSmacallan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1705c1003fSmacallan * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1805c1003fSmacallan * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1905c1003fSmacallan * MICHAEL LORENZ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 2005c1003fSmacallan * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2105c1003fSmacallan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2205c1003fSmacallan */ 2305c1003fSmacallan 242d0d2c2bSmacallan/* $NetBSD: nv_exa.c,v 1.3 2018/07/16 16:30:04 macallan Exp $ */ 2505c1003fSmacallan 2605c1003fSmacallan#ifdef HAVE_CONFIG_H 2705c1003fSmacallan#include "config.h" 2805c1003fSmacallan#endif 2905c1003fSmacallan 3005c1003fSmacallan#include "nv_include.h" 3105c1003fSmacallan#include "miline.h" 3205c1003fSmacallan#include "nv_dma.h" 3305c1003fSmacallan#include "exa.h" 3405c1003fSmacallan 3505c1003fSmacallan//#define DEBUG 3605c1003fSmacallan 3705c1003fSmacallan#ifdef DEBUG 3805c1003fSmacallan#define ENTER xf86Msg(X_ERROR, "%s\n", __func__) 3905c1003fSmacallan#define LEAVE xf86Msg(X_ERROR, "%s done\n", __func__) 4005c1003fSmacallan#else 4105c1003fSmacallan#define ENTER 4205c1003fSmacallan#define LEAVE 4305c1003fSmacallan#endif 4405c1003fSmacallan 4505c1003fSmacallanstatic void 4605c1003fSmacallanNvWaitMarker(ScreenPtr pScreen, int Marker) 4705c1003fSmacallan{ 4805c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 4905c1003fSmacallan 5005c1003fSmacallan ENTER; 5105c1003fSmacallan NVSync(pScrn); 5205c1003fSmacallan LEAVE; 5305c1003fSmacallan} 5405c1003fSmacallan 5505c1003fSmacallanstatic Bool 5605c1003fSmacallanNvPrepareCopy 5705c1003fSmacallan( 5805c1003fSmacallan PixmapPtr pSrcPixmap, 5905c1003fSmacallan PixmapPtr pDstPixmap, 6005c1003fSmacallan int xdir, 6105c1003fSmacallan int ydir, 6205c1003fSmacallan int rop, 6305c1003fSmacallan Pixel planemask 6405c1003fSmacallan) 6505c1003fSmacallan{ 6605c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 6705c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 6805c1003fSmacallan int srcpitch, srcoff, dstpitch, dstoff; 6905c1003fSmacallan 7005c1003fSmacallan ENTER; 7105c1003fSmacallan if (pSrcPixmap->drawable.bitsPerPixel != 32) 7205c1003fSmacallan xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pSrcPixmap->drawable.bitsPerPixel); 7305c1003fSmacallan planemask |= ~0 << pNv->CurrentLayout.depth; 7405c1003fSmacallan NVSetRopSolid(pScrn, rop, planemask); 7505c1003fSmacallan pNv->DMAKickoffCallback = NVDMAKickoffCallback; 7605c1003fSmacallan dstpitch = exaGetPixmapPitch(pDstPixmap); 7705c1003fSmacallan dstoff = exaGetPixmapOffset(pDstPixmap); 7805c1003fSmacallan srcpitch = exaGetPixmapPitch(pSrcPixmap); 7905c1003fSmacallan srcoff = exaGetPixmapOffset(pSrcPixmap); 8005c1003fSmacallan 8105c1003fSmacallan NVDmaStart(pNv, SURFACE_PITCH, 3); 8205c1003fSmacallan NVDmaNext (pNv, srcpitch | (dstpitch << 16)); 8305c1003fSmacallan NVDmaNext (pNv, srcoff); 8405c1003fSmacallan NVDmaNext (pNv, dstoff); 8505c1003fSmacallan 8605c1003fSmacallan LEAVE; 8705c1003fSmacallan return TRUE; 8805c1003fSmacallan} 8905c1003fSmacallan 9005c1003fSmacallanstatic void 9105c1003fSmacallanNvCopy 9205c1003fSmacallan( 9305c1003fSmacallan PixmapPtr pDstPixmap, 9405c1003fSmacallan int srcX, 9505c1003fSmacallan int srcY, 9605c1003fSmacallan int dstX, 9705c1003fSmacallan int dstY, 9805c1003fSmacallan int w, 9905c1003fSmacallan int h 10005c1003fSmacallan) 10105c1003fSmacallan{ 10205c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; 10305c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 10405c1003fSmacallan 10505c1003fSmacallan NVDmaStart(pNv, BLIT_POINT_SRC, 3); 10605c1003fSmacallan NVDmaNext (pNv, (srcY << 16) | srcX); 10705c1003fSmacallan NVDmaNext (pNv, (dstY << 16) | dstX); 10805c1003fSmacallan NVDmaNext (pNv, (h << 16) | w); 10905c1003fSmacallan 11005c1003fSmacallan if((w * h) >= 512) 11105c1003fSmacallan NVDmaKickoff(pNv); 11205c1003fSmacallan 11305c1003fSmacallan LEAVE; 11405c1003fSmacallan} 11505c1003fSmacallan 11605c1003fSmacallanstatic void 11705c1003fSmacallanNvDoneCopy(PixmapPtr pDstPixmap) 11805c1003fSmacallan{ 11905c1003fSmacallan ENTER; 12005c1003fSmacallan LEAVE; 12105c1003fSmacallan} 12205c1003fSmacallan 12305c1003fSmacallanstatic Bool 12405c1003fSmacallanNvPrepareSolid( 12505c1003fSmacallan PixmapPtr pPixmap, 12605c1003fSmacallan int rop, 12705c1003fSmacallan Pixel planemask, 12805c1003fSmacallan Pixel color) 12905c1003fSmacallan{ 13005c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 13105c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 13205c1003fSmacallan int pitch, off; 13305c1003fSmacallan 13405c1003fSmacallan ENTER; 13505c1003fSmacallan if (pPixmap->drawable.bitsPerPixel != 32) 13605c1003fSmacallan xf86Msg(X_ERROR, "%s %d bpp\n", __func__, pPixmap->drawable.bitsPerPixel); 13705c1003fSmacallan planemask |= ~0 << pNv->CurrentLayout.depth; 13805c1003fSmacallan 13905c1003fSmacallan 14005c1003fSmacallan pitch = exaGetPixmapPitch(pPixmap); 14105c1003fSmacallan off = exaGetPixmapOffset(pPixmap); 14205c1003fSmacallan 14305c1003fSmacallan NVDmaStart(pNv, SURFACE_PITCH, 3); 14405c1003fSmacallan NVDmaNext (pNv, pitch | (pitch << 16)); 14505c1003fSmacallan NVDmaNext (pNv, off); 14605c1003fSmacallan NVDmaNext (pNv, off); 14705c1003fSmacallan 14805c1003fSmacallan NVSetRopSolid(pScrn, rop, planemask); 14905c1003fSmacallan pNv->DMAKickoffCallback = NVDMAKickoffCallback; 15005c1003fSmacallan NVDmaStart(pNv, RECT_SOLID_COLOR, 1); 15105c1003fSmacallan NVDmaNext (pNv, color); 15205c1003fSmacallan 15305c1003fSmacallan LEAVE; 15405c1003fSmacallan return TRUE; 15505c1003fSmacallan} 15605c1003fSmacallan 15705c1003fSmacallanstatic void 15805c1003fSmacallanNvSolid( 15905c1003fSmacallan PixmapPtr pPixmap, 16005c1003fSmacallan int x1, 16105c1003fSmacallan int y1, 16205c1003fSmacallan int x2, 16305c1003fSmacallan int y2) 16405c1003fSmacallan{ 16505c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; 16605c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 16705c1003fSmacallan int w = x2 - x1, h = y2 - y1; 16805c1003fSmacallan 16905c1003fSmacallan ENTER; 17005c1003fSmacallan NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2); 17105c1003fSmacallan NVDmaNext (pNv, (x1 << 16) | y1); 17205c1003fSmacallan NVDmaNext (pNv, (w << 16) | h); 17305c1003fSmacallan 17405c1003fSmacallan if((w * h) >= 512) 17505c1003fSmacallan NVDmaKickoff(pNv); 17605c1003fSmacallan 17705c1003fSmacallan LEAVE; 17805c1003fSmacallan} 17905c1003fSmacallan 18005c1003fSmacallan/* 18105c1003fSmacallan * Memcpy-based UTS. 18205c1003fSmacallan */ 18305c1003fSmacallanstatic Bool 18405c1003fSmacallanNvUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, 18505c1003fSmacallan char *src, int src_pitch) 18605c1003fSmacallan{ 18705c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; 18805c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 18905c1003fSmacallan unsigned char *dst = pNv->FbStart + exaGetPixmapOffset(pDst); 19005c1003fSmacallan int dst_pitch = exaGetPixmapPitch(pDst); 19105c1003fSmacallan 19205c1003fSmacallan int bpp = pDst->drawable.bitsPerPixel; 19305c1003fSmacallan int cpp = (bpp + 7) >> 3; 19405c1003fSmacallan int wBytes = w * cpp; 19505c1003fSmacallan 19605c1003fSmacallan ENTER; 19705c1003fSmacallan dst += (x * cpp) + (y * dst_pitch); 19805c1003fSmacallan 19905c1003fSmacallan NVSync(pScrn); 20005c1003fSmacallan 20105c1003fSmacallan while (h--) { 20205c1003fSmacallan memcpy(dst, src, wBytes); 20305c1003fSmacallan src += src_pitch; 20405c1003fSmacallan dst += dst_pitch; 20505c1003fSmacallan } 20605c1003fSmacallan _NV_FENCE() 20705c1003fSmacallan LEAVE; 20805c1003fSmacallan return TRUE; 20905c1003fSmacallan} 21005c1003fSmacallan 21105c1003fSmacallan/* 21205c1003fSmacallan * Memcpy-based DFS. 21305c1003fSmacallan */ 21405c1003fSmacallanstatic Bool 21505c1003fSmacallanNvDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, 21605c1003fSmacallan char *dst, int dst_pitch) 21705c1003fSmacallan{ 21805c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; 21905c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 22005c1003fSmacallan unsigned char *src = pNv->FbStart + exaGetPixmapOffset(pSrc); 22105c1003fSmacallan int src_pitch = exaGetPixmapPitch(pSrc); 22205c1003fSmacallan 22305c1003fSmacallan int bpp = pSrc->drawable.bitsPerPixel; 22405c1003fSmacallan int cpp = (bpp + 7) >> 3; 22505c1003fSmacallan int wBytes = w * cpp; 22605c1003fSmacallan 22705c1003fSmacallan ENTER; 22805c1003fSmacallan src += (x * cpp) + (y * src_pitch); 22905c1003fSmacallan 23005c1003fSmacallan NVSync(pScrn); 23105c1003fSmacallan 23205c1003fSmacallan while (h--) { 23305c1003fSmacallan memcpy(dst, src, wBytes); 23405c1003fSmacallan src += src_pitch; 23505c1003fSmacallan dst += dst_pitch; 23605c1003fSmacallan } 23705c1003fSmacallan LEAVE; 23805c1003fSmacallan return TRUE; 23905c1003fSmacallan} 24005c1003fSmacallan 2412d0d2c2bSmacallanstatic Bool 2422d0d2c2bSmacallanNvPrepareAccess(PixmapPtr pPix, int index) 2432d0d2c2bSmacallan{ 2442d0d2c2bSmacallan ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; 2452d0d2c2bSmacallan 2462d0d2c2bSmacallan NVSync(pScrn); 2472d0d2c2bSmacallan return TRUE; 2482d0d2c2bSmacallan} 2492d0d2c2bSmacallan 2502d0d2c2bSmacallanstatic void 2512d0d2c2bSmacallanNvFinishAccess(PixmapPtr pPix, int index) 2522d0d2c2bSmacallan{ 2532d0d2c2bSmacallan} 2542d0d2c2bSmacallan 25505c1003fSmacallanBool 25605c1003fSmacallanNvInitExa(ScreenPtr pScreen) 25705c1003fSmacallan{ 25805c1003fSmacallan ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 25905c1003fSmacallan NVPtr pNv = NVPTR(pScrn); 26005c1003fSmacallan ExaDriverPtr pExa; 26105c1003fSmacallan int surfaceFormat, rectFormat; 26205c1003fSmacallan 26305c1003fSmacallan pExa = exaDriverAlloc(); 26405c1003fSmacallan if (!pExa) 26505c1003fSmacallan return FALSE; 26605c1003fSmacallan 26705c1003fSmacallan pNv->pExa = pExa; 26805c1003fSmacallan 26905c1003fSmacallan NVResetGraphics(pScrn); 27005c1003fSmacallan 27105c1003fSmacallan pExa->exa_major = EXA_VERSION_MAJOR; 27205c1003fSmacallan pExa->exa_minor = EXA_VERSION_MINOR; 27305c1003fSmacallan 27405c1003fSmacallan pExa->memoryBase = pNv->FbStart; 27505c1003fSmacallan pExa->memorySize = pNv->ScratchBufferStart & (~63); 27605c1003fSmacallan pExa->offScreenBase = pScrn->virtualY * 27705c1003fSmacallan pScrn->displayWidth * pScrn->bitsPerPixel >> 3; 27805c1003fSmacallan pExa->pixmapOffsetAlign = 64; 27905c1003fSmacallan pExa->pixmapPitchAlign = 64; 28005c1003fSmacallan 28105c1003fSmacallan pExa->flags = EXA_OFFSCREEN_PIXMAPS | 28205c1003fSmacallan EXA_SUPPORTS_OFFSCREEN_OVERLAPS | 28305c1003fSmacallan EXA_MIXED_PIXMAPS; 28405c1003fSmacallan 28505c1003fSmacallan pExa->maxX = 8192; 28605c1003fSmacallan pExa->maxY = 8192; 28705c1003fSmacallan 28805c1003fSmacallan pExa->WaitMarker = NvWaitMarker; 28905c1003fSmacallan pExa->PrepareSolid = NvPrepareSolid; 29005c1003fSmacallan pExa->Solid = NvSolid; 29105c1003fSmacallan pExa->DoneSolid = NvDoneCopy; 29205c1003fSmacallan pExa->PrepareCopy = NvPrepareCopy; 29305c1003fSmacallan pExa->Copy = NvCopy; 29405c1003fSmacallan pExa->DoneCopy = NvDoneCopy; 29505c1003fSmacallan 29605c1003fSmacallan switch(pNv->CurrentLayout.depth) { 29705c1003fSmacallan case 24: 29805c1003fSmacallan surfaceFormat = SURFACE_FORMAT_DEPTH24; 29905c1003fSmacallan rectFormat = RECT_FORMAT_DEPTH24; 30005c1003fSmacallan break; 30105c1003fSmacallan case 16: 30205c1003fSmacallan case 15: 30305c1003fSmacallan surfaceFormat = SURFACE_FORMAT_DEPTH16; 30405c1003fSmacallan rectFormat = RECT_FORMAT_DEPTH16; 30505c1003fSmacallan break; 30605c1003fSmacallan default: 30705c1003fSmacallan surfaceFormat = SURFACE_FORMAT_DEPTH8; 30805c1003fSmacallan rectFormat = RECT_FORMAT_DEPTH8; 30905c1003fSmacallan break; 31005c1003fSmacallan } 31105c1003fSmacallan NVDmaStart(pNv, SURFACE_FORMAT, 1); 31205c1003fSmacallan NVDmaNext (pNv, surfaceFormat); 31305c1003fSmacallan NVDmaStart(pNv, RECT_FORMAT, 1); 31405c1003fSmacallan NVDmaNext (pNv, rectFormat); 31505c1003fSmacallan 31605c1003fSmacallan pNv->currentRop = ~0; /* set to something invalid */ 31705c1003fSmacallan NVSetRopSolid(pScrn, GXcopy, ~0); 31805c1003fSmacallan 31905c1003fSmacallan NVDmaKickoff(pNv); 32005c1003fSmacallan 32105c1003fSmacallan /* EXA hits more optimized paths when it does not have to fallback 32205c1003fSmacallan * because of missing UTS/DFS, hook memcpy-based UTS/DFS. 32305c1003fSmacallan */ 32405c1003fSmacallan pExa->UploadToScreen = NvUploadToScreen; 32505c1003fSmacallan pExa->DownloadFromScreen = NvDownloadFromScreen; 3262d0d2c2bSmacallan pExa->PrepareAccess = NvPrepareAccess; 3272d0d2c2bSmacallan pExa->FinishAccess = NvFinishAccess; 3282d0d2c2bSmacallan 32905c1003fSmacallan return exaDriverInit(pScreen, pExa); 33005c1003fSmacallan} 331