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