195b296d0Smrg/* 295b296d0Smrg * Copyright 1997-2003 by Alan Hourihane, North Wales, UK. 395b296d0Smrg * 495b296d0Smrg * Permission to use, copy, modify, distribute, and sell this software and its 595b296d0Smrg * documentation for any purpose is hereby granted without fee, provided that 695b296d0Smrg * the above copyright notice appear in all copies and that both that 795b296d0Smrg * copyright notice and this permission notice appear in supporting 895b296d0Smrg * documentation, and that the name of Alan Hourihane not be used in 995b296d0Smrg * advertising or publicity pertaining to distribution of the software without 1095b296d0Smrg * specific, written prior permission. Alan Hourihane makes no representations 1195b296d0Smrg * about the suitability of this software for any purpose. It is provided 1295b296d0Smrg * "as is" without express or implied warranty. 1395b296d0Smrg * 1495b296d0Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1595b296d0Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1695b296d0Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1795b296d0Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1895b296d0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1995b296d0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2095b296d0Smrg * PERFORMANCE OF THIS SOFTWARE. 2195b296d0Smrg * 2295b296d0Smrg * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> 2395b296d0Smrg */ 2495b296d0Smrg 2595b296d0Smrg#ifdef HAVE_CONFIG_H 2695b296d0Smrg#include "config.h" 2795b296d0Smrg#endif 2895b296d0Smrg 2995b296d0Smrg#include "xf86.h" 3095b296d0Smrg#include "xf86_OSproc.h" 3195b296d0Smrg#include "xf86Pci.h" 3295b296d0Smrg#include "trident.h" 3395b296d0Smrg#include "trident_regs.h" 3495b296d0Smrg#include "dgaproc.h" 3595b296d0Smrg 3695b296d0Smrg 3795b296d0Smrgstatic Bool TRIDENT_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 3895b296d0Smrg int *, int *, int *); 3995b296d0Smrgstatic Bool TRIDENT_SetMode(ScrnInfoPtr, DGAModePtr); 4095b296d0Smrgstatic int TRIDENT_GetViewport(ScrnInfoPtr); 4195b296d0Smrgstatic void TRIDENT_SetViewport(ScrnInfoPtr, int, int, int); 42eca46af7Smrg#ifdef HAVE_XAA_H 43eca46af7Smrgstatic void TRIDENT_Sync(ScrnInfoPtr); 4495b296d0Smrgstatic void TRIDENT_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 4595b296d0Smrgstatic void TRIDENT_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); 4695b296d0Smrg#if 0 4795b296d0Smrgstatic void TRIDENT_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 4895b296d0Smrg unsigned long); 4995b296d0Smrg#endif 50eca46af7Smrg#endif 5195b296d0Smrg 5295b296d0Smrgstatic 5395b296d0SmrgDGAFunctionRec TRIDENTDGAFuncs = { 5495b296d0Smrg TRIDENT_OpenFramebuffer, 5595b296d0Smrg NULL, 5695b296d0Smrg TRIDENT_SetMode, 5795b296d0Smrg TRIDENT_SetViewport, 5895b296d0Smrg TRIDENT_GetViewport, 59eca46af7Smrg#ifdef HAVE_XAA_H 6095b296d0Smrg TRIDENT_Sync, 6195b296d0Smrg TRIDENT_FillRect, 6295b296d0Smrg TRIDENT_BlitRect, 6395b296d0Smrg#if 0 6495b296d0Smrg TRIDENT_BlitTransRect 6595b296d0Smrg#else 6695b296d0Smrg NULL 6795b296d0Smrg#endif 68eca46af7Smrg#else 69eca46af7Smrg NULL, NULL, NULL 70eca46af7Smrg#endif 7195b296d0Smrg}; 7295b296d0Smrg 7395b296d0SmrgBool 7495b296d0SmrgTRIDENTDGAInit(ScreenPtr pScreen) 7595b296d0Smrg{ 76eca46af7Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 7795b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 7895b296d0Smrg DGAModePtr modes = NULL, newmodes = NULL, currentMode; 7995b296d0Smrg DisplayModePtr pMode, firstMode; 8095b296d0Smrg int Bpp = pScrn->bitsPerPixel >> 3; 8195b296d0Smrg int num = 0; 8295b296d0Smrg Bool oneMore; 8395b296d0Smrg 8495b296d0Smrg pMode = firstMode = pScrn->modes; 8595b296d0Smrg 8695b296d0Smrg while(pMode) { 8795b296d0Smrg 8895b296d0Smrg if(0 /*pScrn->displayWidth != pMode->HDisplay*/) { 8914330f12Smrg newmodes = realloc(modes, (num + 2) * sizeof(DGAModeRec)); 9095b296d0Smrg oneMore = TRUE; 9195b296d0Smrg } else { 9214330f12Smrg newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); 9395b296d0Smrg oneMore = FALSE; 9495b296d0Smrg } 9595b296d0Smrg 9695b296d0Smrg if(!newmodes) { 9714330f12Smrg free(modes); 9895b296d0Smrg return FALSE; 9995b296d0Smrg } 10095b296d0Smrg modes = newmodes; 10195b296d0Smrg 10295b296d0SmrgSECOND_PASS: 10395b296d0Smrg 10495b296d0Smrg currentMode = modes + num; 10595b296d0Smrg num++; 10695b296d0Smrg 10795b296d0Smrg currentMode->mode = pMode; 10895b296d0Smrg currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; 109eca46af7Smrg#ifdef HAVE_XAA_H 11095b296d0Smrg if(!pTrident->NoAccel) 11195b296d0Smrg currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; 112eca46af7Smrg#endif 11395b296d0Smrg if(pMode->Flags & V_DBLSCAN) 11495b296d0Smrg currentMode->flags |= DGA_DOUBLESCAN; 11595b296d0Smrg if(pMode->Flags & V_INTERLACE) 11695b296d0Smrg currentMode->flags |= DGA_INTERLACED; 11795b296d0Smrg currentMode->byteOrder = pScrn->imageByteOrder; 11895b296d0Smrg currentMode->depth = pScrn->depth; 11995b296d0Smrg currentMode->bitsPerPixel = pScrn->bitsPerPixel; 12095b296d0Smrg currentMode->red_mask = pScrn->mask.red; 12195b296d0Smrg currentMode->green_mask = pScrn->mask.green; 12295b296d0Smrg currentMode->blue_mask = pScrn->mask.blue; 12395b296d0Smrg currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; 12495b296d0Smrg currentMode->viewportWidth = pMode->HDisplay; 12595b296d0Smrg currentMode->viewportHeight = pMode->VDisplay; 12695b296d0Smrg currentMode->xViewportStep = 1; 12795b296d0Smrg currentMode->yViewportStep = 1; 12895b296d0Smrg currentMode->viewportFlags = DGA_FLIP_RETRACE; 12995b296d0Smrg currentMode->offset = 0; 13095b296d0Smrg currentMode->address = pTrident->FbBase; 13195b296d0Smrg 13295b296d0Smrg if(oneMore) { /* first one is narrow width */ 13395b296d0Smrg currentMode->bytesPerScanline = ((pMode->HDisplay * Bpp) + 3) & ~3L; 13495b296d0Smrg currentMode->imageWidth = pMode->HDisplay; 13595b296d0Smrg currentMode->imageHeight = pMode->VDisplay; 13695b296d0Smrg currentMode->pixmapWidth = currentMode->imageWidth; 13795b296d0Smrg currentMode->pixmapHeight = currentMode->imageHeight; 13895b296d0Smrg currentMode->maxViewportX = currentMode->imageWidth - 13995b296d0Smrg currentMode->viewportWidth; 14095b296d0Smrg /* this might need to get clamped to some maximum */ 14195b296d0Smrg currentMode->maxViewportY = currentMode->imageHeight - 14295b296d0Smrg currentMode->viewportHeight; 14395b296d0Smrg oneMore = FALSE; 14495b296d0Smrg goto SECOND_PASS; 14595b296d0Smrg } else { 14695b296d0Smrg currentMode->bytesPerScanline = 14795b296d0Smrg ((pScrn->displayWidth * Bpp) + 3) & ~3L; 14895b296d0Smrg currentMode->imageWidth = pScrn->displayWidth; 14995b296d0Smrg currentMode->imageHeight = pMode->VDisplay; 15095b296d0Smrg currentMode->pixmapWidth = currentMode->imageWidth; 15195b296d0Smrg currentMode->pixmapHeight = currentMode->imageHeight; 15295b296d0Smrg currentMode->maxViewportX = currentMode->imageWidth - 15395b296d0Smrg currentMode->viewportWidth; 15495b296d0Smrg /* this might need to get clamped to some maximum */ 15595b296d0Smrg currentMode->maxViewportY = currentMode->imageHeight - 15695b296d0Smrg currentMode->viewportHeight; 15795b296d0Smrg } 15895b296d0Smrg 15995b296d0Smrg pMode = pMode->next; 16095b296d0Smrg if(pMode == firstMode) 16195b296d0Smrg break; 16295b296d0Smrg } 16395b296d0Smrg 16495b296d0Smrg pTrident->numDGAModes = num; 16595b296d0Smrg pTrident->DGAModes = modes; 16695b296d0Smrg 16795b296d0Smrg return DGAInit(pScreen, &TRIDENTDGAFuncs, modes, num); 16895b296d0Smrg} 16995b296d0Smrg 17095b296d0Smrg 17195b296d0Smrgstatic Bool 17295b296d0SmrgTRIDENT_SetMode( 17395b296d0Smrg ScrnInfoPtr pScrn, 17495b296d0Smrg DGAModePtr pMode 17595b296d0Smrg){ 17695b296d0Smrg static int OldDisplayWidth[MAXSCREENS]; 17795b296d0Smrg int index = pScrn->pScreen->myNum; 17895b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 17995b296d0Smrg 18095b296d0Smrg if(!pMode) { /* restore the original mode */ 18195b296d0Smrg /* put the ScreenParameters back */ 18295b296d0Smrg 18395b296d0Smrg pScrn->displayWidth = OldDisplayWidth[index]; 18495b296d0Smrg 185eca46af7Smrg TRIDENTSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)); 18695b296d0Smrg pTrident->DGAactive = FALSE; 18795b296d0Smrg } else { 18895b296d0Smrg if(!pTrident->DGAactive) { /* save the old parameters */ 18995b296d0Smrg OldDisplayWidth[index] = pScrn->displayWidth; 19095b296d0Smrg 19195b296d0Smrg pTrident->DGAactive = TRUE; 19295b296d0Smrg } 19395b296d0Smrg 19495b296d0Smrg pScrn->displayWidth = pMode->bytesPerScanline / 19595b296d0Smrg (pMode->bitsPerPixel >> 3); 19695b296d0Smrg 197eca46af7Smrg TRIDENTSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode)); 19895b296d0Smrg } 19995b296d0Smrg 20095b296d0Smrg return TRUE; 20195b296d0Smrg} 20295b296d0Smrg 20395b296d0Smrg 20495b296d0Smrg 20595b296d0Smrgstatic int 20695b296d0SmrgTRIDENT_GetViewport( 20795b296d0Smrg ScrnInfoPtr pScrn 20895b296d0Smrg){ 20995b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 21095b296d0Smrg 21195b296d0Smrg return pTrident->DGAViewportStatus; 21295b296d0Smrg} 21395b296d0Smrg 21495b296d0Smrgstatic void 21595b296d0SmrgTRIDENT_SetViewport( 21695b296d0Smrg ScrnInfoPtr pScrn, 21795b296d0Smrg int x, int y, 21895b296d0Smrg int flags 21995b296d0Smrg){ 22095b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 22195b296d0Smrg 222eca46af7Smrg TRIDENTAdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y)); 22395b296d0Smrg pTrident->DGAViewportStatus = 0; /* TRIDENTAdjustFrame loops until finished */ 22495b296d0Smrg} 22595b296d0Smrg 226eca46af7Smrg#ifdef HAVE_XAA_H 22795b296d0Smrgstatic void 22895b296d0SmrgTRIDENT_FillRect ( 22995b296d0Smrg ScrnInfoPtr pScrn, 23095b296d0Smrg int x, int y, int w, int h, 23195b296d0Smrg unsigned long color 23295b296d0Smrg){ 23395b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 23495b296d0Smrg 23595b296d0Smrg if(pTrident->AccelInfoRec) { 23695b296d0Smrg (*pTrident->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0); 23795b296d0Smrg (*pTrident->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h); 23895b296d0Smrg SET_SYNC_FLAG(pTrident->AccelInfoRec); 23995b296d0Smrg } 24095b296d0Smrg} 24195b296d0Smrg 24295b296d0Smrgstatic void 24395b296d0SmrgTRIDENT_Sync( 24495b296d0Smrg ScrnInfoPtr pScrn 24595b296d0Smrg){ 24695b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 24795b296d0Smrg 24895b296d0Smrg if(pTrident->AccelInfoRec) { 24995b296d0Smrg (*pTrident->AccelInfoRec->Sync)(pScrn); 25095b296d0Smrg } 25195b296d0Smrg} 25295b296d0Smrg 25395b296d0Smrgstatic void 25495b296d0SmrgTRIDENT_BlitRect( 25595b296d0Smrg ScrnInfoPtr pScrn, 25695b296d0Smrg int srcx, int srcy, 25795b296d0Smrg int w, int h, 25895b296d0Smrg int dstx, int dsty 25995b296d0Smrg){ 26095b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 26195b296d0Smrg 26295b296d0Smrg if(pTrident->AccelInfoRec) { 26395b296d0Smrg int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; 26495b296d0Smrg int ydir = (srcy < dsty) ? -1 : 1; 26595b296d0Smrg 26695b296d0Smrg (*pTrident->AccelInfoRec->SetupForScreenToScreenCopy)( 26795b296d0Smrg pScrn, xdir, ydir, GXcopy, ~0, -1); 26895b296d0Smrg (*pTrident->AccelInfoRec->SubsequentScreenToScreenCopy)( 26995b296d0Smrg pScrn, srcx, srcy, dstx, dsty, w, h); 27095b296d0Smrg SET_SYNC_FLAG(pTrident->AccelInfoRec); 27195b296d0Smrg } 27295b296d0Smrg} 27395b296d0Smrg 27495b296d0Smrg#if 0 27595b296d0Smrgstatic void 27695b296d0SmrgTRIDENT_BlitTransRect( 27795b296d0Smrg ScrnInfoPtr pScrn, 27895b296d0Smrg int srcx, int srcy, 27995b296d0Smrg int w, int h, 28095b296d0Smrg int dstx, int dsty, 28195b296d0Smrg unsigned long color 28295b296d0Smrg){ 28395b296d0Smrg /* this one should be separate since the XAA function would 28495b296d0Smrg prohibit usage of ~0 as the key */ 28595b296d0Smrg} 28695b296d0Smrg#endif 287eca46af7Smrg#endif 28895b296d0Smrg 28995b296d0Smrgstatic Bool 29095b296d0SmrgTRIDENT_OpenFramebuffer( 29195b296d0Smrg ScrnInfoPtr pScrn, 29295b296d0Smrg char **name, 29395b296d0Smrg unsigned char **mem, 29495b296d0Smrg int *size, 29595b296d0Smrg int *offset, 29695b296d0Smrg int *flags 29795b296d0Smrg){ 29895b296d0Smrg TRIDENTPtr pTrident = TRIDENTPTR(pScrn); 29995b296d0Smrg 30095b296d0Smrg *name = NULL; /* no special device */ 30195b296d0Smrg *mem = (unsigned char*)pTrident->FbAddress; 30295b296d0Smrg *size = pTrident->FbMapSize; 30395b296d0Smrg *offset = 0; 30495b296d0Smrg *flags = DGA_NEED_ROOT; 30595b296d0Smrg 30695b296d0Smrg return TRUE; 30795b296d0Smrg} 308