s3_dga.c revision bd35f0db
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 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "xf86.h" 33#include "xf86_OSproc.h" 34 35#include "dgaproc.h" 36 37#include "s3.h" 38#include "s3_reg.h" 39 40 41static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode); 42static int S3_GetViewport(ScrnInfoPtr pScrn); 43static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags); 44static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, 45 unsigned long color); 46static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, 47 int dstx, int dsty); 48static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, 49 unsigned char **mem, int *size, int *offset, 50 int *flags); 51static void S3_Sync(ScrnInfoPtr pScrn); 52 53 54static DGAFunctionRec S3_DGAFuncs = { 55 S3_OpenFramebuffer, 56 NULL, 57 S3_SetMode, 58 S3_SetViewport, 59 S3_GetViewport, 60 S3_Sync, 61 S3_FillRect, 62 S3_BltRect, 63 NULL 64}; 65 66 67static DGAModePtr S3SetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, 68 int *num, int bitsPerPixel, int depth, 69 Bool pixmap, int secondPitch, 70 unsigned long red, unsigned long green, 71 unsigned long blue, short visualClass) 72{ 73 S3Ptr pS3 = S3PTR(pScrn); 74 DGAModePtr newmodes = NULL, currentMode; 75 DisplayModePtr pMode, firstMode; 76 int otherPitch, Bpp = bitsPerPixel >> 3; 77 Bool oneMore; 78 79 pMode = firstMode = pScrn->modes; 80 81 while (pMode) { 82 otherPitch = secondPitch ? secondPitch : pMode->HDisplay; 83 84 if (pMode->HDisplay != otherPitch) { 85 newmodes = xrealloc(modes, (*num + 2) * sizeof(DGAModeRec)); 86 oneMore = TRUE; 87 } else { 88 newmodes = xrealloc(modes, (*num + 1) * sizeof(DGAModeRec)); 89 oneMore = FALSE; 90 } 91 92 if (!newmodes) { 93 xfree(modes); 94 return NULL; 95 } 96 97 modes = newmodes; 98 99SECOND_PASS: 100 101 currentMode = modes + *num; 102 (*num)++; 103 104 currentMode->mode = pMode; 105 currentMode->flags = DGA_CONCURRENT_ACCESS; 106 if (pixmap) 107 currentMode->flags |= DGA_PIXMAP_AVAILABLE; 108 if (pS3->pXAA) 109 currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; 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 = depth; 116 currentMode->bitsPerPixel = bitsPerPixel; 117 currentMode->red_mask = red; 118 currentMode->green_mask = green; 119 currentMode->blue_mask = blue; 120 currentMode->visualClass = visualClass; 121 currentMode->viewportWidth = pMode->HDisplay; 122 currentMode->viewportHeight = pMode->VDisplay; 123 currentMode->xViewportStep = 8; 124 currentMode->yViewportStep = 1; 125 currentMode->viewportFlags = DGA_FLIP_RETRACE; 126 currentMode->offset = 0; 127 currentMode->address = (unsigned char*)pS3->FBAddress; 128 129 if (oneMore) { 130 currentMode->bytesPerScanline = (((pMode->HDisplay * Bpp) + 3) & ~3L); 131 132 currentMode->imageWidth = pMode->HDisplay; 133 currentMode->imageHeight = pMode->VDisplay; 134 currentMode->pixmapWidth = currentMode->imageWidth; 135 currentMode->pixmapHeight = currentMode->imageHeight; 136 currentMode->maxViewportX = currentMode->imageWidth - 137 currentMode->viewportWidth; 138 currentMode->maxViewportY = currentMode->imageHeight - 139 currentMode->viewportHeight; 140 141 oneMore = FALSE; 142 goto SECOND_PASS; 143 } else { 144 currentMode->bytesPerScanline = (((otherPitch * Bpp) + 3) & ~3L); 145 146 currentMode->imageWidth = otherPitch; 147 currentMode->imageHeight = pMode->VDisplay; 148 currentMode->pixmapWidth = currentMode->imageWidth; 149 currentMode->pixmapHeight = currentMode->imageHeight; 150 currentMode->maxViewportX = currentMode->imageWidth - 151 currentMode->viewportWidth; 152 currentMode->maxViewportY = currentMode->imageHeight - 153 currentMode->viewportHeight; 154 155 } 156 157 pMode = pMode->next; 158 159 if (pMode == firstMode) 160 break; 161 162 } 163 164 return modes; 165} 166 167 168 169Bool S3DGAInit(ScreenPtr pScreen) 170{ 171 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 172 S3Ptr pS3 = S3PTR(pScrn); 173 DGAModePtr modes = NULL; 174 int num = 0; 175 176 modes = S3SetupDGAMode(pScrn, modes, &num, 8, 8, 177 (pScrn->bitsPerPixel == 8), 178 ((pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth), 179 0, 0, 0, PseudoColor); 180 181 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, 182 (pScrn->bitsPerPixel == 16), 183 ((pScrn->depth != 15) 184 ? 0 : pScrn->displayWidth), 185 0x7c00, 0x03e0, 0x001f, TrueColor); 186 187 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 15, 188 (pScrn->bitsPerPixel == 16), 189 ((pScrn->depth != 15) 190 ? 0 : pScrn->displayWidth), 191 0x7c00, 0x03e0, 0x001f, DirectColor); 192 193 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, 194 (pScrn->bitsPerPixel == 16), 195 ((pScrn->depth != 16) 196 ? 0 : pScrn->displayWidth), 197 0xf800, 0x07e0, 0x001f, TrueColor); 198 199 modes = S3SetupDGAMode(pScrn, modes, &num, 16, 16, 200 (pScrn->bitsPerPixel == 16), 201 ((pScrn->depth != 16) 202 ? 0 : pScrn->displayWidth), 203 0xf800, 0x07e0, 0x001f, DirectColor); 204 205 modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, 206 (pScrn->bitsPerPixel == 32), 207 ((pScrn->bitsPerPixel != 32) 208 ? 0 : pScrn->displayWidth), 209 0xff0000, 0x00ff00, 0x0000ff, TrueColor); 210 211 modes = S3SetupDGAMode(pScrn, modes, &num, 32, 24, 212 (pScrn->bitsPerPixel == 32), 213 ((pScrn->bitsPerPixel != 32) 214 ? 0 : pScrn->displayWidth), 215 0xff0000, 0x00ff00, 0x0000ff, DirectColor); 216 217 pS3->numDGAModes = num; 218 pS3->DGAModes = modes; 219 220 return DGAInit(pScreen, &S3_DGAFuncs, modes, num); 221} 222 223 224static Bool S3_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) 225{ 226 S3Ptr pS3 = S3PTR(pScrn); 227 static S3FBLayout SavedLayouts[MAXSCREENS]; 228 int indx = pScrn->pScreen->myNum; 229 230 if (!pMode) { 231 if (pS3->DGAactive) { 232 memcpy(&pS3->CurrentLayout, &SavedLayouts[indx], 233 sizeof(S3FBLayout)); 234 pS3->DGAactive = TRUE; 235 } 236 237 pS3->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel; 238 pS3->CurrentLayout.depth = pMode->depth; 239 pS3->CurrentLayout.displayWidth = (pMode->bytesPerScanline / 240 (pMode->bitsPerPixel >> 3)); 241 pS3->CurrentLayout.pixel_bytes = pMode->bitsPerPixel / 8; 242 pS3->CurrentLayout.pixel_code = (pMode->bitsPerPixel != 16 ? 243 pMode->bitsPerPixel : 244 pMode->depth); 245 246 S3SwitchMode(indx, pMode->mode, 0); 247 } 248 249 return TRUE; 250} 251 252 253static int S3_GetViewport(ScrnInfoPtr pScrn) 254{ 255 S3Ptr pS3 = S3PTR(pScrn); 256 257 return pS3->DGAViewportStatus; 258} 259 260 261static void S3_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) 262{ 263 S3Ptr pS3 = S3PTR(pScrn); 264 265 pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags); 266 pS3->DGAViewportStatus = 0; 267} 268 269 270static void S3_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, 271 unsigned long color) 272{ 273 S3Ptr pS3 = S3PTR(pScrn); 274 275 if (pS3->pXAA) { 276 (*pS3->pXAA->SetupForSolidFill)(pScrn, color, GXcopy, (CARD32)(~0)); 277 (*pS3->pXAA->SubsequentSolidFillRect)(pScrn, x, y, w, h); 278 SET_SYNC_FLAG(pS3->pXAA); 279 } 280} 281 282 283static void S3_BltRect(ScrnInfoPtr pScrn, int srcx, int srcy, int w, int h, 284 int dstx, int dsty) 285{ 286 S3Ptr pS3 = S3PTR(pScrn); 287 288 if (pS3->pXAA) { 289 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 290 int ydir = (srcy < dsty) ? -1 : 1; 291 292 (*pS3->pXAA->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, 293 GXcopy, (CARD32)(~0), -1); 294 (*pS3->pXAA->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, 295 dstx, dsty, w, h); 296 SET_SYNC_FLAG(pS3->pXAA); 297 } 298} 299 300 301static Bool S3_OpenFramebuffer(ScrnInfoPtr pScrn, char **name, 302 unsigned char **mem, int *size, int *offset, 303 int *flags) 304{ 305 S3Ptr pS3 = S3PTR(pScrn); 306 307 *name = NULL; 308 *mem = (unsigned char*)pS3->FBAddress; 309 *size = (pScrn->videoRam * 1024); 310 *offset = 0; 311 *flags = 0; 312 313 return TRUE; 314} 315 316 317static void S3_Sync(ScrnInfoPtr pScrn) 318{ 319 WaitIdle(); 320} 321