neo_dga.c revision 3f6d0e1d
1692f60a7Smrg/* 2692f60a7Smrg * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. 3692f60a7Smrg * 4692f60a7Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5692f60a7Smrg * documentation for any purpose is hereby granted without fee, provided that 6692f60a7Smrg * the above copyright notice appear in all copies and that both that 7692f60a7Smrg * copyright notice and this permission notice appear in supporting 8692f60a7Smrg * documentation, and that the name of Alan Hourihane not be used in 9692f60a7Smrg * advertising or publicity pertaining to distribution of the software without 10692f60a7Smrg * specific, written prior permission. Alan Hourihane makes no representations 11692f60a7Smrg * about the suitability of this software for any purpose. It is provided 12692f60a7Smrg * "as is" without express or implied warranty. 13692f60a7Smrg * 14692f60a7Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15692f60a7Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16692f60a7Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17692f60a7Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18692f60a7Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19692f60a7Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20692f60a7Smrg * PERFORMANCE OF THIS SOFTWARE. 21692f60a7Smrg * 22692f60a7Smrg * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 23692f60a7Smrg */ 24692f60a7Smrg 25692f60a7Smrg#ifdef HAVE_CONFIG_H 26692f60a7Smrg#include "config.h" 27692f60a7Smrg#endif 28692f60a7Smrg 29692f60a7Smrg#include "xf86.h" 30692f60a7Smrg#include "xf86_OSproc.h" 31692f60a7Smrg#include "xf86Pci.h" 32692f60a7Smrg#include "xf86PciInfo.h" 33692f60a7Smrg#include "neo.h" 34692f60a7Smrg#include "neo_reg.h" 35692f60a7Smrg#include "dgaproc.h" 36692f60a7Smrg#include "vgaHW.h" 37692f60a7Smrg 38692f60a7Smrgstatic Bool NEO_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 39692f60a7Smrg int *, int *, int *); 40692f60a7Smrgstatic Bool NEO_SetMode(ScrnInfoPtr, DGAModePtr); 41692f60a7Smrgstatic void NEO_Sync(ScrnInfoPtr); 42692f60a7Smrgstatic int NEO_GetViewport(ScrnInfoPtr); 43692f60a7Smrgstatic void NEO_SetViewport(ScrnInfoPtr, int, int, int); 443f6d0e1dSmrg#ifdef HAVE_XAA_H 45692f60a7Smrgstatic void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 46692f60a7Smrgstatic void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); 47692f60a7Smrg#if 0 48692f60a7Smrgstatic void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 49692f60a7Smrg unsigned long); 50692f60a7Smrg#endif 513f6d0e1dSmrg#endif 52692f60a7Smrg 53692f60a7Smrgstatic 54692f60a7SmrgDGAFunctionRec NEODGAFuncs = { 55692f60a7Smrg NEO_OpenFramebuffer, 56692f60a7Smrg NULL, 57692f60a7Smrg NEO_SetMode, 58692f60a7Smrg NEO_SetViewport, 59692f60a7Smrg NEO_GetViewport, 60692f60a7Smrg NEO_Sync, 613f6d0e1dSmrg#ifdef HAVE_XAA_H 62692f60a7Smrg NEO_FillRect, 63692f60a7Smrg NEO_BlitRect, 64692f60a7Smrg#if 0 65692f60a7Smrg NEO_BlitTransRect 66692f60a7Smrg#else 67692f60a7Smrg NULL 68692f60a7Smrg#endif 693f6d0e1dSmrg#else 703f6d0e1dSmrg NULL, NULL, NULL 713f6d0e1dSmrg#endif 72692f60a7Smrg}; 73692f60a7Smrg 74692f60a7SmrgBool 75692f60a7SmrgNEODGAInit(ScreenPtr pScreen) 76692f60a7Smrg{ 773f6d0e1dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 78692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 79692f60a7Smrg DGAModePtr modes = NULL, newmodes = NULL, currentMode; 80692f60a7Smrg DisplayModePtr pMode, firstMode; 81692f60a7Smrg int Bpp = pScrn->bitsPerPixel >> 3; 82692f60a7Smrg int num = 0, imlines, pixlines; 83692f60a7Smrg 84692f60a7Smrg imlines = (pScrn->videoRam * 1024) / 85692f60a7Smrg (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); 86692f60a7Smrg 87692f60a7Smrg pixlines = (imlines > 1024 && !pNEO->noAccel) ? 1024 : imlines; 88692f60a7Smrg 89692f60a7Smrg pMode = firstMode = pScrn->modes; 90692f60a7Smrg 91692f60a7Smrg while(pMode) { 92692f60a7Smrg 933f6d0e1dSmrg newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); 94692f60a7Smrg 95692f60a7Smrg if(!newmodes) { 963f6d0e1dSmrg free(modes); 97692f60a7Smrg return FALSE; 98692f60a7Smrg } 99692f60a7Smrg modes = newmodes; 100692f60a7Smrg 101692f60a7Smrg currentMode = modes + num; 102692f60a7Smrg num++; 103692f60a7Smrg 104692f60a7Smrg currentMode->mode = pMode; 105692f60a7Smrg currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 1063f6d0e1dSmrg#ifdef HAVE_XAA_H 107692f60a7Smrg if (!pNEO->noAccel) 108692f60a7Smrg currentMode->flags |= (DGA_FILL_RECT | DGA_BLIT_RECT); 1093f6d0e1dSmrg#endif 110692f60a7Smrg if(pMode->Flags & V_DBLSCAN) 111692f60a7Smrg currentMode->flags |= DGA_DOUBLESCAN; 112692f60a7Smrg if(pMode->Flags & V_INTERLACE) 113692f60a7Smrg currentMode->flags |= DGA_INTERLACED; 114692f60a7Smrg currentMode->byteOrder = pScrn->imageByteOrder; 115692f60a7Smrg currentMode->depth = pScrn->depth; 116692f60a7Smrg currentMode->bitsPerPixel = pScrn->bitsPerPixel; 117692f60a7Smrg currentMode->red_mask = pScrn->mask.red; 118692f60a7Smrg currentMode->green_mask = pScrn->mask.green; 119692f60a7Smrg currentMode->blue_mask = pScrn->mask.blue; 120692f60a7Smrg currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; 121692f60a7Smrg currentMode->viewportWidth = pMode->HDisplay; 122692f60a7Smrg currentMode->viewportHeight = pMode->VDisplay; 123692f60a7Smrg currentMode->xViewportStep = 1; 124692f60a7Smrg currentMode->yViewportStep = 1; 125692f60a7Smrg currentMode->viewportFlags = DGA_FLIP_RETRACE; 126692f60a7Smrg currentMode->offset = 0; 127692f60a7Smrg currentMode->address = pNEO->NeoFbBase; 128692f60a7Smrg 129692f60a7Smrg currentMode->bytesPerScanline = 130692f60a7Smrg ((pScrn->displayWidth * Bpp) + 3) & ~3L; 131692f60a7Smrg currentMode->imageWidth = pScrn->displayWidth; 132692f60a7Smrg currentMode->imageHeight = imlines; 133692f60a7Smrg currentMode->pixmapWidth = currentMode->imageWidth; 134692f60a7Smrg currentMode->pixmapHeight = pixlines; 135692f60a7Smrg currentMode->maxViewportX = currentMode->imageWidth - 136692f60a7Smrg currentMode->viewportWidth; 137692f60a7Smrg currentMode->maxViewportY = currentMode->imageHeight - 138692f60a7Smrg currentMode->viewportHeight; 139692f60a7Smrg 140692f60a7Smrg pMode = pMode->next; 141692f60a7Smrg if(pMode == firstMode) 142692f60a7Smrg break; 143692f60a7Smrg } 144692f60a7Smrg 145692f60a7Smrg pNEO->numDGAModes = num; 146692f60a7Smrg pNEO->DGAModes = modes; 147692f60a7Smrg 148692f60a7Smrg return DGAInit(pScreen, &NEODGAFuncs, modes, num); 149692f60a7Smrg} 150692f60a7Smrg 151692f60a7Smrgstatic DisplayModePtr NEOSavedDGAModes[MAXSCREENS]; 152692f60a7Smrg 153692f60a7Smrgstatic Bool 154692f60a7SmrgNEO_SetMode( 155692f60a7Smrg ScrnInfoPtr pScrn, 156692f60a7Smrg DGAModePtr pMode 157692f60a7Smrg){ 158692f60a7Smrg int index = pScrn->pScreen->myNum; 159692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 160692f60a7Smrg 161692f60a7Smrg if(!pMode) { /* restore the original mode */ 162692f60a7Smrg if(pNEO->DGAactive) { 163692f60a7Smrg pScrn->currentMode = NEOSavedDGAModes[index]; 1643f6d0e1dSmrg NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)); 1653f6d0e1dSmrg NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0)); 166692f60a7Smrg pNEO->DGAactive = FALSE; 167692f60a7Smrg } 168692f60a7Smrg } else { 169692f60a7Smrg if(!pNEO->DGAactive) { /* save the old parameters */ 170692f60a7Smrg NEOSavedDGAModes[index] = pScrn->currentMode; 171692f60a7Smrg pNEO->DGAactive = TRUE; 172692f60a7Smrg } 173692f60a7Smrg 1743f6d0e1dSmrg NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode)); 175692f60a7Smrg } 176692f60a7Smrg 177692f60a7Smrg return TRUE; 178692f60a7Smrg} 179692f60a7Smrg 180692f60a7Smrgstatic int 181692f60a7SmrgNEO_GetViewport( 182692f60a7Smrg ScrnInfoPtr pScrn 183692f60a7Smrg){ 184692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 185692f60a7Smrg 186692f60a7Smrg return pNEO->DGAViewportStatus; 187692f60a7Smrg} 188692f60a7Smrg 189692f60a7Smrgstatic void 190692f60a7SmrgNEO_SetViewport( 191692f60a7Smrg ScrnInfoPtr pScrn, 192692f60a7Smrg int x, int y, 193692f60a7Smrg int flags 194692f60a7Smrg){ 195692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 196692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 197692f60a7Smrg 1983f6d0e1dSmrg NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y)); 199692f60a7Smrg /* wait for retrace */ 200692f60a7Smrg while((hwp->readST01(hwp) & 0x08)); 201692f60a7Smrg while(!(hwp->readST01(hwp) & 0x08)); 202692f60a7Smrg 203692f60a7Smrg pNEO->DGAViewportStatus = 0; 204692f60a7Smrg} 205692f60a7Smrg 2063f6d0e1dSmrg#ifdef HAVE_XAA_H 207692f60a7Smrgstatic void 208692f60a7SmrgNEO_FillRect ( 209692f60a7Smrg ScrnInfoPtr pScrn, 210692f60a7Smrg int x, int y, int w, int h, 211692f60a7Smrg unsigned long color 212692f60a7Smrg){ 213692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 214692f60a7Smrg 215692f60a7Smrg if(pNEO->AccelInfoRec) { 216692f60a7Smrg (*pNEO->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); 217692f60a7Smrg (*pNEO->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 218692f60a7Smrg SET_SYNC_FLAG(pNEO->AccelInfoRec); 219692f60a7Smrg } 220692f60a7Smrg} 221692f60a7Smrg 2223f6d0e1dSmrg 223692f60a7Smrgstatic void 224692f60a7SmrgNEO_Sync( 225692f60a7Smrg ScrnInfoPtr pScrn 226692f60a7Smrg){ 227692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 2283f6d0e1dSmrg#ifdef HAVE_XAA_H 229692f60a7Smrg if(pNEO->AccelInfoRec) { 230692f60a7Smrg (*pNEO->AccelInfoRec->Sync)(pScrn); 231692f60a7Smrg } 2323f6d0e1dSmrg#endif 233692f60a7Smrg} 234692f60a7Smrg 235692f60a7Smrgstatic void 236692f60a7SmrgNEO_BlitRect( 237692f60a7Smrg ScrnInfoPtr pScrn, 238692f60a7Smrg int srcx, int srcy, 239692f60a7Smrg int w, int h, 240692f60a7Smrg int dstx, int dsty 241692f60a7Smrg){ 242692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 243692f60a7Smrg 244692f60a7Smrg if(pNEO->AccelInfoRec) { 245692f60a7Smrg int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 246692f60a7Smrg int ydir = (srcy < dsty) ? -1 : 1; 247692f60a7Smrg 248692f60a7Smrg (*pNEO->AccelInfoRec->SetupForScreenToScreenCopy)( 249692f60a7Smrg pScrn, xdir, ydir, GXcopy, ~0, -1); 250692f60a7Smrg (*pNEO->AccelInfoRec->SubsequentScreenToScreenCopy)( 251692f60a7Smrg pScrn, srcx, srcy, dstx, dsty, w, h); 252692f60a7Smrg SET_SYNC_FLAG(pNEO->AccelInfoRec); 253692f60a7Smrg } 254692f60a7Smrg} 255692f60a7Smrg 256692f60a7Smrg#if 0 257692f60a7Smrgstatic void 258692f60a7SmrgNEO_BlitTransRect( 259692f60a7Smrg ScrnInfoPtr pScrn, 260692f60a7Smrg int srcx, int srcy, 261692f60a7Smrg int w, int h, 262692f60a7Smrg int dstx, int dsty, 263692f60a7Smrg unsigned long color 264692f60a7Smrg){ 265692f60a7Smrg /* this one should be separate since the XAA function would 266692f60a7Smrg prohibit usage of ~0 as the key */ 267692f60a7Smrg} 268692f60a7Smrg#endif 2693f6d0e1dSmrg#endif 270692f60a7Smrgstatic Bool 271692f60a7SmrgNEO_OpenFramebuffer( 272692f60a7Smrg ScrnInfoPtr pScrn, 273692f60a7Smrg char **name, 274692f60a7Smrg unsigned char **mem, 275692f60a7Smrg int *size, 276692f60a7Smrg int *offset, 277692f60a7Smrg int *flags 278692f60a7Smrg){ 279692f60a7Smrg NEOPtr pNEO = NEOPTR(pScrn); 280692f60a7Smrg 281692f60a7Smrg *name = NULL; /* no special device */ 282692f60a7Smrg *mem = (unsigned char*)pNEO->NeoLinearAddr; 283692f60a7Smrg *size = pNEO->NeoFbMapSize; 284692f60a7Smrg *offset = 0; 285692f60a7Smrg *flags = DGA_NEED_ROOT; 286692f60a7Smrg 287692f60a7Smrg return TRUE; 288692f60a7Smrg} 2893f6d0e1dSmrg 290