neo_dga.c revision 3f6d0e1d
1/* 2 * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Alan Hourihane not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Alan Hourihane makes no representations 11 * about the suitability of this software for any purpose. It is provided 12 * "as is" without express or implied warranty. 13 * 14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 * 22 * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "xf86.h" 30#include "xf86_OSproc.h" 31#include "xf86Pci.h" 32#include "xf86PciInfo.h" 33#include "neo.h" 34#include "neo_reg.h" 35#include "dgaproc.h" 36#include "vgaHW.h" 37 38static Bool NEO_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 39 int *, int *, int *); 40static Bool NEO_SetMode(ScrnInfoPtr, DGAModePtr); 41static void NEO_Sync(ScrnInfoPtr); 42static int NEO_GetViewport(ScrnInfoPtr); 43static void NEO_SetViewport(ScrnInfoPtr, int, int, int); 44#ifdef HAVE_XAA_H 45static void NEO_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 46static void NEO_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); 47#if 0 48static void NEO_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 49 unsigned long); 50#endif 51#endif 52 53static 54DGAFunctionRec NEODGAFuncs = { 55 NEO_OpenFramebuffer, 56 NULL, 57 NEO_SetMode, 58 NEO_SetViewport, 59 NEO_GetViewport, 60 NEO_Sync, 61#ifdef HAVE_XAA_H 62 NEO_FillRect, 63 NEO_BlitRect, 64#if 0 65 NEO_BlitTransRect 66#else 67 NULL 68#endif 69#else 70 NULL, NULL, NULL 71#endif 72}; 73 74Bool 75NEODGAInit(ScreenPtr pScreen) 76{ 77 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 78 NEOPtr pNEO = NEOPTR(pScrn); 79 DGAModePtr modes = NULL, newmodes = NULL, currentMode; 80 DisplayModePtr pMode, firstMode; 81 int Bpp = pScrn->bitsPerPixel >> 3; 82 int num = 0, imlines, pixlines; 83 84 imlines = (pScrn->videoRam * 1024) / 85 (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); 86 87 pixlines = (imlines > 1024 && !pNEO->noAccel) ? 1024 : imlines; 88 89 pMode = firstMode = pScrn->modes; 90 91 while(pMode) { 92 93 newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); 94 95 if(!newmodes) { 96 free(modes); 97 return FALSE; 98 } 99 modes = newmodes; 100 101 currentMode = modes + num; 102 num++; 103 104 currentMode->mode = pMode; 105 currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 106#ifdef HAVE_XAA_H 107 if (!pNEO->noAccel) 108 currentMode->flags |= (DGA_FILL_RECT | DGA_BLIT_RECT); 109#endif 110 if(pMode->Flags & V_DBLSCAN) 111 currentMode->flags |= DGA_DOUBLESCAN; 112 if(pMode->Flags & V_INTERLACE) 113 currentMode->flags |= DGA_INTERLACED; 114 currentMode->byteOrder = pScrn->imageByteOrder; 115 currentMode->depth = pScrn->depth; 116 currentMode->bitsPerPixel = pScrn->bitsPerPixel; 117 currentMode->red_mask = pScrn->mask.red; 118 currentMode->green_mask = pScrn->mask.green; 119 currentMode->blue_mask = pScrn->mask.blue; 120 currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; 121 currentMode->viewportWidth = pMode->HDisplay; 122 currentMode->viewportHeight = pMode->VDisplay; 123 currentMode->xViewportStep = 1; 124 currentMode->yViewportStep = 1; 125 currentMode->viewportFlags = DGA_FLIP_RETRACE; 126 currentMode->offset = 0; 127 currentMode->address = pNEO->NeoFbBase; 128 129 currentMode->bytesPerScanline = 130 ((pScrn->displayWidth * Bpp) + 3) & ~3L; 131 currentMode->imageWidth = pScrn->displayWidth; 132 currentMode->imageHeight = imlines; 133 currentMode->pixmapWidth = currentMode->imageWidth; 134 currentMode->pixmapHeight = pixlines; 135 currentMode->maxViewportX = currentMode->imageWidth - 136 currentMode->viewportWidth; 137 currentMode->maxViewportY = currentMode->imageHeight - 138 currentMode->viewportHeight; 139 140 pMode = pMode->next; 141 if(pMode == firstMode) 142 break; 143 } 144 145 pNEO->numDGAModes = num; 146 pNEO->DGAModes = modes; 147 148 return DGAInit(pScreen, &NEODGAFuncs, modes, num); 149} 150 151static DisplayModePtr NEOSavedDGAModes[MAXSCREENS]; 152 153static Bool 154NEO_SetMode( 155 ScrnInfoPtr pScrn, 156 DGAModePtr pMode 157){ 158 int index = pScrn->pScreen->myNum; 159 NEOPtr pNEO = NEOPTR(pScrn); 160 161 if(!pMode) { /* restore the original mode */ 162 if(pNEO->DGAactive) { 163 pScrn->currentMode = NEOSavedDGAModes[index]; 164 NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)); 165 NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0)); 166 pNEO->DGAactive = FALSE; 167 } 168 } else { 169 if(!pNEO->DGAactive) { /* save the old parameters */ 170 NEOSavedDGAModes[index] = pScrn->currentMode; 171 pNEO->DGAactive = TRUE; 172 } 173 174 NEOSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode)); 175 } 176 177 return TRUE; 178} 179 180static int 181NEO_GetViewport( 182 ScrnInfoPtr pScrn 183){ 184 NEOPtr pNEO = NEOPTR(pScrn); 185 186 return pNEO->DGAViewportStatus; 187} 188 189static void 190NEO_SetViewport( 191 ScrnInfoPtr pScrn, 192 int x, int y, 193 int flags 194){ 195 NEOPtr pNEO = NEOPTR(pScrn); 196 vgaHWPtr hwp = VGAHWPTR(pScrn); 197 198 NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y)); 199 /* wait for retrace */ 200 while((hwp->readST01(hwp) & 0x08)); 201 while(!(hwp->readST01(hwp) & 0x08)); 202 203 pNEO->DGAViewportStatus = 0; 204} 205 206#ifdef HAVE_XAA_H 207static void 208NEO_FillRect ( 209 ScrnInfoPtr pScrn, 210 int x, int y, int w, int h, 211 unsigned long color 212){ 213 NEOPtr pNEO = NEOPTR(pScrn); 214 215 if(pNEO->AccelInfoRec) { 216 (*pNEO->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); 217 (*pNEO->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 218 SET_SYNC_FLAG(pNEO->AccelInfoRec); 219 } 220} 221 222 223static void 224NEO_Sync( 225 ScrnInfoPtr pScrn 226){ 227 NEOPtr pNEO = NEOPTR(pScrn); 228#ifdef HAVE_XAA_H 229 if(pNEO->AccelInfoRec) { 230 (*pNEO->AccelInfoRec->Sync)(pScrn); 231 } 232#endif 233} 234 235static void 236NEO_BlitRect( 237 ScrnInfoPtr pScrn, 238 int srcx, int srcy, 239 int w, int h, 240 int dstx, int dsty 241){ 242 NEOPtr pNEO = NEOPTR(pScrn); 243 244 if(pNEO->AccelInfoRec) { 245 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 246 int ydir = (srcy < dsty) ? -1 : 1; 247 248 (*pNEO->AccelInfoRec->SetupForScreenToScreenCopy)( 249 pScrn, xdir, ydir, GXcopy, ~0, -1); 250 (*pNEO->AccelInfoRec->SubsequentScreenToScreenCopy)( 251 pScrn, srcx, srcy, dstx, dsty, w, h); 252 SET_SYNC_FLAG(pNEO->AccelInfoRec); 253 } 254} 255 256#if 0 257static void 258NEO_BlitTransRect( 259 ScrnInfoPtr pScrn, 260 int srcx, int srcy, 261 int w, int h, 262 int dstx, int dsty, 263 unsigned long color 264){ 265 /* this one should be separate since the XAA function would 266 prohibit usage of ~0 as the key */ 267} 268#endif 269#endif 270static Bool 271NEO_OpenFramebuffer( 272 ScrnInfoPtr pScrn, 273 char **name, 274 unsigned char **mem, 275 int *size, 276 int *offset, 277 int *flags 278){ 279 NEOPtr pNEO = NEOPTR(pScrn); 280 281 *name = NULL; /* no special device */ 282 *mem = (unsigned char*)pNEO->NeoLinearAddr; 283 *size = pNEO->NeoFbMapSize; 284 *offset = 0; 285 *flags = DGA_NEED_ROOT; 286 287 return TRUE; 288} 289 290