1#ifdef HAVE_CONFIG_H 2#include "config.h" 3#endif 4 5#include "xf86.h" 6#include "xf86_OSproc.h" 7#include "xf86Pci.h" 8#include "mga.h" 9#include "mga_reg.h" 10#include "dgaproc.h" 11 12 13static Bool MGA_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 14 int *, int *, int *); 15static Bool MGA_SetMode(ScrnInfoPtr, DGAModePtr); 16static int MGA_GetViewport(ScrnInfoPtr); 17static void MGA_SetViewport(ScrnInfoPtr, int, int, int); 18#ifdef USE_XAA 19static void MGA_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 20static void MGA_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); 21static void MGA_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 22 unsigned long); 23#endif 24 25static 26DGAFunctionRec MGA_DGAFuncs = { 27 MGA_OpenFramebuffer, 28 NULL, 29 MGA_SetMode, 30 MGA_SetViewport, 31 MGA_GetViewport, 32 MGAStormSync, 33#ifdef USE_XAA 34 MGA_FillRect, 35 MGA_BlitRect, 36 MGA_BlitTransRect 37#else 38 NULL, NULL, NULL 39#endif 40}; 41 42 43static int 44FindSmallestPitch( 45 MGAPtr pMga, 46 int Bpp, 47 int width 48){ 49 int Pitches1[] = 50 {640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0}; 51 int Pitches2[] = 52 {512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 53 1920, 2048, 0}; 54 int *linePitches = NULL; 55 int pitch; 56 57 58 if(!pMga->NoAccel) { 59 switch(pMga->Chipset) { 60 case PCI_CHIP_MGA2064: 61 linePitches = Pitches1; 62 break; 63 case PCI_CHIP_MGA2164: 64 case PCI_CHIP_MGA2164_AGP: 65 case PCI_CHIP_MGA1064: 66 linePitches = Pitches2; 67 break; 68 } 69 } 70 71 pitch = pMga->Roundings[Bpp - 1] - 1; 72 73 if(linePitches) { 74 while((*linePitches < width) || (*linePitches & pitch)) 75 linePitches++; 76 return *linePitches; 77 } 78 79 return ((width + pitch) & ~pitch); 80} 81 82static DGAModePtr 83MGASetupDGAMode( 84 ScrnInfoPtr pScrn, 85 DGAModePtr modes, 86 int *num, 87 int bitsPerPixel, 88 int depth, 89 Bool pixmap, 90 int secondPitch, 91 unsigned long red, 92 unsigned long green, 93 unsigned long blue, 94 short visualClass 95){ 96 DisplayModePtr firstMode, pMode; 97 MGAPtr pMga = MGAPTR(pScrn); 98 DGAModePtr mode, newmodes; 99 int size, pitch, Bpp = bitsPerPixel >> 3; 100 101SECOND_PASS: 102 103 pMode = firstMode = pScrn->modes; 104 105 while(1) { 106 107 108 pitch = FindSmallestPitch(pMga, Bpp, pMode->HDisplay); 109 size = pitch * Bpp * pMode->VDisplay; 110 111 if((!secondPitch || (pitch != secondPitch)) && 112 (size <= pMga->FbUsableSize)) { 113 114 if(secondPitch) 115 pitch = secondPitch; 116 117 if(!(newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec)))) 118 break; 119 120 modes = newmodes; 121 mode = modes + *num; 122 123 mode->mode = pMode; 124 mode->flags = DGA_CONCURRENT_ACCESS; 125 if(pixmap) 126 mode->flags |= DGA_PIXMAP_AVAILABLE; 127#ifdef USE_XAA 128 if(!pMga->NoAccel) { 129 mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; 130 if((Bpp != 3) && (pMga->Chipset != PCI_CHIP_MGA2064)) 131 mode->flags |= DGA_BLIT_RECT_TRANS; 132 } 133#endif 134 if(pMode->Flags & V_DBLSCAN) 135 mode->flags |= DGA_DOUBLESCAN; 136 if(pMode->Flags & V_INTERLACE) 137 mode->flags |= DGA_INTERLACED; 138 mode->byteOrder = pScrn->imageByteOrder; 139 mode->depth = depth; 140 mode->bitsPerPixel = bitsPerPixel; 141 mode->red_mask = red; 142 mode->green_mask = green; 143 mode->blue_mask = blue; 144 mode->visualClass = visualClass; 145 mode->viewportWidth = pMode->HDisplay; 146 mode->viewportHeight = pMode->VDisplay; 147 mode->xViewportStep = (3 - pMga->BppShifts[Bpp - 1]); 148 if((Bpp == 3) && 149 (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)) 150 mode->xViewportStep <<= 1; 151 mode->yViewportStep = 1; 152 mode->viewportFlags = DGA_FLIP_RETRACE; 153 mode->offset = pMga->YDstOrg * Bpp; /* gonna need to fix that */ 154 mode->address = pMga->FbStart; 155 mode->bytesPerScanline = pitch * Bpp; 156 mode->imageWidth = pitch; 157 mode->imageHeight = pMga->FbUsableSize / mode->bytesPerScanline; 158 mode->pixmapWidth = pitch; 159 switch (pMga->Chipset) { 160 case PCI_CHIP_MGAG200_SE_A_PCI: 161 case PCI_CHIP_MGAG200_SE_B_PCI: 162 mode->pixmapHeight = (min(pMga->FbUsableSize, 1*1024*1024)) / 163 mode->bytesPerScanline; 164 break; 165 default: 166 mode->pixmapHeight = (min(pMga->FbUsableSize, 16*1024*1024)) / 167 mode->bytesPerScanline; 168 } 169 mode->maxViewportX = mode->imageWidth - mode->viewportWidth; 170 mode->maxViewportY = (pMga->FbUsableSize / mode->bytesPerScanline) - 171 mode->viewportHeight; 172 173 if( (pMga->Chipset == PCI_CHIP_MGA2064) || 174 (pMga->Chipset == PCI_CHIP_MGA2164) || 175 (pMga->Chipset == PCI_CHIP_MGA2164_AGP)) 176 { 177 int tmp; 178 179 tmp = (8*1024*1024 / mode->bytesPerScanline) - 180 mode->viewportHeight; 181 if(tmp < 0) tmp = 0; 182 if(tmp < mode->maxViewportY) 183 mode->maxViewportY = tmp; 184 } 185 186 (*num)++; 187 } 188 189 pMode = pMode->next; 190 if(pMode == firstMode) 191 break; 192 } 193 194 if(secondPitch) { 195 secondPitch = 0; 196 goto SECOND_PASS; 197 } 198 199 return modes; 200} 201 202 203Bool 204MGADGAInit(ScreenPtr pScreen) 205{ 206 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 207 MGAPtr pMga = MGAPTR(pScrn); 208 DGAModePtr modes = NULL; 209 int num = 0; 210 211 /* 8 */ 212 modes = MGASetupDGAMode (pScrn, modes, &num, 8, 8, 213 (pScrn->bitsPerPixel == 8), 214 (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth, 215 0, 0, 0, PseudoColor); 216 217 /* 15 */ 218 modes = MGASetupDGAMode (pScrn, modes, &num, 16, 15, 219 (pScrn->bitsPerPixel == 16), 220 (pScrn->depth != 15) ? 0 : pScrn->displayWidth, 221 0x7c00, 0x03e0, 0x001f, TrueColor); 222 223 modes = MGASetupDGAMode (pScrn, modes, &num, 16, 15, 224 (pScrn->bitsPerPixel == 16), 225 (pScrn->depth != 15) ? 0 : pScrn->displayWidth, 226 0x7c00, 0x03e0, 0x001f, DirectColor); 227 228 /* 16 */ 229 modes = MGASetupDGAMode (pScrn, modes, &num, 16, 16, 230 (pScrn->bitsPerPixel == 16), 231 (pScrn->depth != 16) ? 0 : pScrn->displayWidth, 232 0xf800, 0x07e0, 0x001f, TrueColor); 233 234 modes = MGASetupDGAMode (pScrn, modes, &num, 16, 16, 235 (pScrn->bitsPerPixel == 16), 236 (pScrn->depth != 16) ? 0 : pScrn->displayWidth, 237 0xf800, 0x07e0, 0x001f, DirectColor); 238 239 /* 24 */ 240 modes = MGASetupDGAMode (pScrn, modes, &num, 24, 24, 241 (pScrn->bitsPerPixel == 24), 242 (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth, 243 0xff0000, 0x00ff00, 0x0000ff, TrueColor); 244 245 modes = MGASetupDGAMode (pScrn, modes, &num, 24, 24, 246 (pScrn->bitsPerPixel == 24), 247 (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth, 248 0xff0000, 0x00ff00, 0x0000ff, DirectColor); 249 250 /* 32 */ 251 modes = MGASetupDGAMode (pScrn, modes, &num, 32, 24, 252 (pScrn->bitsPerPixel == 32), 253 (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth, 254 0xff0000, 0x00ff00, 0x0000ff, TrueColor); 255 256 modes = MGASetupDGAMode (pScrn, modes, &num, 32, 24, 257 (pScrn->bitsPerPixel == 32), 258 (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth, 259 0xff0000, 0x00ff00, 0x0000ff, DirectColor); 260 261 pMga->numDGAModes = num; 262 pMga->DGAModes = modes; 263 264 return DGAInit(pScreen, &MGA_DGAFuncs, modes, num); 265} 266 267 268static int 269BitsSet(unsigned long data) 270{ 271 unsigned long mask; 272 int set = 0; 273 274 for(mask = 1; mask; mask <<= 1) 275 if(mask & data) set++; 276 277 return set; 278} 279 280/* 281 * This is not strictly required - but it will load a 'sane' 282 * palette when starting DGA. 283 */ 284static void 285mgaDGASetPalette(ScrnInfoPtr pScrn) 286{ 287 MGAPtr pMga = MGAPTR(pScrn); 288 MGARamdacPtr MGAdac = &pMga->Dac; 289 unsigned char DAC[256*3]; 290 int i; 291 292 if (!MGAdac->RestorePalette) 293 return; 294 295 for (i = 0; i < 256; i++) { 296 DAC[i*3] = i; 297 DAC[i*3 + 1] = i; 298 DAC[i*3 + 2] = i; 299 } 300 MGAdac->RestorePalette(pScrn, DAC); 301} 302 303 304static Bool 305MGA_SetMode( 306 ScrnInfoPtr pScrn, 307 DGAModePtr pMode 308){ 309 static MGAFBLayout SavedLayouts[MAXSCREENS]; 310 int index = pScrn->pScreen->myNum; 311 312 MGAPtr pMga = MGAPTR(pScrn); 313 314 if(!pMode) { /* restore the original mode */ 315 if(pMga->DGAactive) 316 memcpy(&pMga->CurrentLayout, &SavedLayouts[index], sizeof(MGAFBLayout)); 317 318 pScrn->currentMode = pMga->CurrentLayout.mode; 319 pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)); 320 MGAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 321 pMga->DGAactive = FALSE; 322 } else { 323 if(!pMga->DGAactive) { /* save the old parameters */ 324 memcpy(&SavedLayouts[index], &pMga->CurrentLayout, sizeof(MGAFBLayout)); 325 pMga->DGAactive = TRUE; 326 } 327 /* update CurrentLayout */ 328 pMga->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; 329 pMga->CurrentLayout.depth = pMode->depth; 330 pMga->CurrentLayout.displayWidth = pMode->bytesPerScanline / 331 (pMode->bitsPerPixel >> 3); 332 pMga->CurrentLayout.weight.red = BitsSet(pMode->red_mask); 333 pMga->CurrentLayout.weight.green = BitsSet(pMode->green_mask); 334 pMga->CurrentLayout.weight.blue = BitsSet(pMode->blue_mask); 335 /* MGAModeInit() will set the mode field */ 336 337 pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode)); 338 /* not strictly required but nice */ 339 mgaDGASetPalette(pScrn); 340 } 341 342 return TRUE; 343} 344 345 346 347static int 348MGA_GetViewport( 349 ScrnInfoPtr pScrn 350){ 351 MGAPtr pMga = MGAPTR(pScrn); 352 353 return pMga->DGAViewportStatus; 354} 355 356static void 357MGA_SetViewport( 358 ScrnInfoPtr pScrn, 359 int x, int y, 360 int flags 361){ 362 MGAPtr pMga = MGAPTR(pScrn); 363 364 MGAAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y)); 365 pMga->DGAViewportStatus = 0; /* MGAAdjustFrame loops until finished */ 366} 367 368#ifdef USE_XAA 369static void 370MGA_FillRect ( 371 ScrnInfoPtr pScrn, 372 int x, int y, int w, int h, 373 unsigned long color 374){ 375 MGAPtr pMga = MGAPTR(pScrn); 376 377 if(!pMga->AccelInfoRec) return; 378 379 mgaDoSetupForSolidFill(pScrn, color, GXcopy, ~0, 380 pMga->CurrentLayout.bitsPerPixel); 381 (*pMga->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 382 383 SET_SYNC_FLAG(pMga->AccelInfoRec); 384} 385 386static void 387MGA_BlitRect( 388 ScrnInfoPtr pScrn, 389 int srcx, int srcy, 390 int w, int h, 391 int dstx, int dsty 392){ 393 MGAPtr pMga = MGAPTR(pScrn); 394 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 395 int ydir = (srcy < dsty) ? -1 : 1; 396 397 if(!pMga->AccelInfoRec) return; 398 399 mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, GXcopy, ~0, -1, 400 pMga->CurrentLayout.bitsPerPixel ); 401 402 (*pMga->AccelInfoRec->SubsequentScreenToScreenCopy)( 403 pScrn, srcx, srcy, dstx, dsty, w, h); 404 405 SET_SYNC_FLAG(pMga->AccelInfoRec); 406} 407 408 409static void MGA_BlitTransRect( ScrnInfoPtr pScrn, int srcx, int srcy, 410 int w, int h, int dstx, int dsty, 411 unsigned long color ) 412{ 413 MGAPtr pMga = MGAPTR(pScrn); 414 415 if( (pMga->AccelInfoRec != NULL) 416 && (pMga->CurrentLayout.bitsPerPixel != 24) 417 && (pMga->Chipset != PCI_CHIP_MGA2064) ) { 418 const int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 419 const int ydir = (srcy < dsty) ? -1 : 1; 420 421 pMga->DrawTransparent = TRUE; 422 423 mgaDoSetupForScreenToScreenCopy( pScrn, xdir, ydir, GXcopy, ~0, color, 424 pMga->CurrentLayout.bitsPerPixel ); 425 426 pMga->DrawTransparent = FALSE; 427 428 (*pMga->AccelInfoRec->SubsequentScreenToScreenCopy)( 429 pScrn, srcx, srcy, dstx, dsty, w, h); 430 431 SET_SYNC_FLAG(pMga->AccelInfoRec); 432 } 433} 434#endif 435 436static Bool 437MGA_OpenFramebuffer( 438 ScrnInfoPtr pScrn, 439 char **name, 440 unsigned char **mem, 441 int *size, 442 int *offset, 443 int *flags 444){ 445 MGAPtr pMga = MGAPTR(pScrn); 446 447 *name = NULL; /* no special device */ 448 *mem = (unsigned char*)pMga->FbAddress; 449 *size = pMga->FbMapSize; 450 *offset = 0; 451 *flags = DGA_NEED_ROOT; 452 453 return TRUE; 454} 455