s3_dga.c revision 340e3fbd
1/* 2 * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> 3 * 4 * XFree86 4.x driver for S3 chipsets 5 * 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that copyright 10 * notice and this permission notice appear in supporting documentation and 11 * that the name of Ani Joshi not be used in advertising or 12 * publicity pertaining to distribution of the software without specific, 13 * written prior permission. Ani Joshi makes no representations 14 * about the suitability of this software for any purpose. It is provided 15 * "as-is" without express or implied warranty. 16 * 17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 * 25 * 26 */ 27/* $XFree86: $ */ 28 29#ifdef HAVE_CONFIG_H 30#include "config.h" 31#endif 32 33#include "xf86.h" 34#include "xf86_OSproc.h" 35 36#include "dgaproc.h" 37 38#include "s3.h" 39#include "s3_reg.h" 40 41 42static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode); 43static int S3_GetViewport(ScrnInfoPtr pScrn); 44static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 45static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, 46 unsigned long color); 47static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, 48 int dstx, int dsty); 49static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, 50 unsigned char **mem, int *size, int *offset, 51 int *flags); 52static void S3_Sync(ScrnInfoPtr pScrn); 53 54 55static DGAFunctionRec S3_DGAFuncs = { 56 S3_OpenFramebuffer, 57 NULL, 58 S3_SetMode, 59 S3_SetViewport, 60 S3_GetViewport, 61 S3_Sync, 62 S3_FillRect, 63 S3_BltRect, 64 NULL 65}; 66 67 68static DGAModePtr S3SetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, 69 int *num, int bitsPerPixel, int depth, 70 Bool pixmap, int secondPitch, 71 unsigned long red, unsigned long green, 72 unsigned long blue, short visualClass) 73{ 74 S3Ptr pS3 = S3PTR(pScrn); 75 DGAModePtr newmodes = NULL, currentMode; 76 DisplayModePtr pMode, firstMode; 77 int otherPitch, Bpp = bitsPerPixel >> 3; 78 Bool oneMore; 79 80 pMode = firstMode = pScrn->modes; 81 82 while (pMode) { 83 otherPitch = secondPitch ? secondPitch : pMode->HDisplay; 84 85 if (pMode->HDisplay != otherPitch) { 86 newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec)); 87 oneMore = TRUE; 88 } else { 89 newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)); 90 oneMore = FALSE; 91 } 92 93 if (!newmodes) { 94 xfree(modes); 95 return NULL; 96 } 97 98 modes = newmodes; 99 100SECOND_PASS: 101 102 currentMode = modes + *num; 103 (*num)++; 104 105 currentMode->mode = pMode; 106 currentMode->flags = DGA_CONCURRENT_ACCESS; 107 if (pixmap) 108 currentMode->flags |= DGA_PIXMAP_AVAILABLE; 109 if (pS3->pXAA) 110 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; 111 if (pMode->Flags & V_DBLSCAN) 112 currentMode->flags |= DGA_DOUBLESCAN; 113 if (pMode->Flags & V_INTERLACE) 114 currentMode->flags |= DGA_INTERLACED; 115 currentMode->byteOrder = pScrn->imageByteOrder; 116 currentMode->depth = depth; 117 currentMode->bitsPerPixel = bitsPerPixel; 118 currentMode->red_mask = red; 119 currentMode->green_mask = green; 120 currentMode->blue_mask = blue; 121 currentMode->visualClass = visualClass; 122 currentMode->viewportWidth = pMode->HDisplay; 123 currentMode->viewportHeight = pMode->VDisplay; 124 currentMode->xViewportStep = 8; 125 currentMode->yViewportStep = 1; 126 currentMode->viewportFlags = DGA_FLIP_RETRACE; 127 currentMode->offset = 0; 128 currentMode->address = (unsigned char*)pS3->FBAddress; 129 130 if (oneMore) { 131 currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L); 132 133 currentMode->imageWidth = pMode->HDisplay; 134 currentMode->imageHeight = pMode->VDisplay; 135 currentMode->pixmapWidth = currentMode->imageWidth; 136 currentMode->pixmapHeight = currentMode->imageHeight; 137 currentMode->maxViewportX = currentMode->imageWidth - 138 currentMode->viewportWidth; 139 currentMode->maxViewportY = currentMode->imageHeight - 140 currentMode->viewportHeight; 141 142 oneMore = FALSE; 143 goto SECOND_PASS; 144 } else { 145 currentMode->bytesPerScanline = (((otherPitch * Bpp) + 3) & ~3L); 146 147 currentMode->imageWidth = otherPitch; 148 currentMode->imageHeight = pMode->VDisplay; 149 currentMode->pixmapWidth = currentMode->imageWidth; 150 currentMode->pixmapHeight = currentMode->imageHeight; 151 currentMode->maxViewportX = currentMode->imageWidth - 152 currentMode->viewportWidth; 153 currentMode->maxViewportY = currentMode->imageHeight - 154 currentMode->viewportHeight; 155 156 } 157 158 pMode = pMode->next; 159 160 if (pMode == firstMode) 161 break; 162 163 } 164 165 return modes; 166} 167 168 169 170Bool S3DGAInit(ScreenPtr pScreen) 171{ 172 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 173 S3Ptr pS3 = S3PTR(pScrn); 174 DGAModePtr modes = NULL; 175 int num = 0; 176 177 modes = S3SetupDGAMode(pScrn, modes, &num, 8, 8, 178 (pScrn->bitsPerPixel == 8), 179 ((pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth), 180 0, 0, 0, PseudoColor); 181 182 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, 183 (pScrn->bitsPerPixel == 16), 184 ((pScrn->depth != 15) 185 ? 0 : pScrn->displayWidth), 186 0x7c00, 0x03e0, 0x001f, TrueColor); 187 188 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, 189 (pScrn->bitsPerPixel == 16), 190 ((pScrn->depth != 15) 191 ? 0 : pScrn->displayWidth), 192 0x7c00, 0x03e0, 0x001f, DirectColor); 193 194 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, 195 (pScrn->bitsPerPixel == 16), 196 ((pScrn->depth != 16) 197 ? 0 : pScrn->displayWidth), 198 0xf800, 0x07e0, 0x001f, TrueColor); 199 200 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, 201 (pScrn->bitsPerPixel == 16), 202 ((pScrn->depth != 16) 203 ? 0 : pScrn->displayWidth), 204 0xf800, 0x07e0, 0x001f, DirectColor); 205 206 modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, 207 (pScrn->bitsPerPixel == 32), 208 ((pScrn->bitsPerPixel != 32) 209 ? 0 : pScrn->displayWidth), 210 0xff0000, 0x00ff00, 0x0000ff, TrueColor); 211 212 modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, 213 (pScrn->bitsPerPixel == 32), 214 ((pScrn->bitsPerPixel != 32) 215 ? 0 : pScrn->displayWidth), 216 0xff0000, 0x00ff00, 0x0000ff, DirectColor); 217 218 pS3->numDGAModes = num; 219 pS3->DGAModes = modes; 220 221 return DGAInit(pScreen, &S3_DGAFuncs, modes, num); 222} 223 224 225static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) 226{ 227 S3Ptr pS3 = S3PTR(pScrn); 228 static S3FBLayout SavedLayouts[MAXSCREENS]; 229 int indx = pScrn->pScreen->myNum; 230 231 if (!pMode) { 232 if (pS3->DGAactive) { 233 memcpy(&pS3->CurrentLayout, &SavedLayouts[indx], 234 sizeof(S3FBLayout)); 235 pS3->DGAactive = TRUE; 236 } 237 238 pS3->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; 239 pS3->CurrentLayout.depth = pMode->depth; 240 pS3->CurrentLayout.displayWidth = (pMode->bytesPerScanline / 241 (pMode->bitsPerPixel >> 3)); 242 pS3->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8; 243 pS3->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16 ? 244 pMode->bitsPerPixel : 245 pMode->depth); 246 247 S3SwitchMode(indx, pMode->mode, 0); 248 } 249 250 return TRUE; 251} 252 253 254static int S3_GetViewport(ScrnInfoPtr pScrn) 255{ 256 S3Ptr pS3 = S3PTR(pScrn); 257 258 return pS3->DGAViewportStatus; 259} 260 261 262static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 263{ 264 S3Ptr pS3 = S3PTR(pScrn); 265 266 pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags); 267 pS3->DGAViewportStatus = 0; 268} 269 270 271static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, 272 unsigned long color) 273{ 274 S3Ptr pS3 = S3PTR(pScrn); 275 276 if (pS3->pXAA) { 277 (*pS3->pXAA->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0)); 278 (*pS3->pXAA->SubsequentSolidFillRect)(pScrn, x, y, w, h); 279 SET_SYNC_FLAG(pS3->pXAA); 280 } 281} 282 283 284static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, 285 int dstx, int dsty) 286{ 287 S3Ptr pS3 = S3PTR(pScrn); 288 289 if (pS3->pXAA) { 290 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 291 int ydir = (srcy < dsty) ? -1 : 1; 292 293 (*pS3->pXAA->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, 294 GXcopy, (CARD32)(~0), -1); 295 (*pS3->pXAA->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, 296 dstx, dsty, w, h); 297 SET_SYNC_FLAG(pS3->pXAA); 298 } 299} 300 301 302static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, 303 unsigned char **mem, int *size, int *offset, 304 int *flags) 305{ 306 S3Ptr pS3 = S3PTR(pScrn); 307 308 *name = NULL; 309 *mem = (unsigned char*)pS3->FBAddress; 310 *size = (pScrn->videoRam * 1024); 311 *offset = 0; 312 *flags = 0; 313 314 return TRUE; 315} 316 317 318static void S3_Sync(ScrnInfoPtr pScrn) 319{ 320 WaitIdle(); 321} 322