tseng_dga.c revision d983712d
1d983712dSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tseng/tseng_dga.c,v 1.1 2000/12/06 15:35:24 eich Exp $ */
2d983712dSmrg/*
3d983712dSmrg * Copyright 2000 by Rainer Keller, <Rainer.Keller@studmail.uni-stuttgart.de>.
4d983712dSmrg *
5d983712dSmrg * Permission to use, copy, modify, distribute, and sell this software and its
6d983712dSmrg * documentation for any purpose is hereby granted without fee, provided that
7d983712dSmrg * the above copyright notice appear in all copies and that both that
8d983712dSmrg * copyright notice and this permission notice appear in supporting
9d983712dSmrg * documentation, and that the name of Alan Hourihane not be used in
10d983712dSmrg * advertising or publicity pertaining to distribution of the software without
11d983712dSmrg * specific, written prior permission.  Alan Hourihane makes no representations
12d983712dSmrg * about the suitability of this software for any purpose.  It is provided
13d983712dSmrg * "as is" without express or implied warranty.
14d983712dSmrg *
15d983712dSmrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16d983712dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17d983712dSmrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18d983712dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19d983712dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20d983712dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21d983712dSmrg * PERFORMANCE OF THIS SOFTWARE.
22d983712dSmrg *
23d983712dSmrg * Authors:  Adapted from: Alan Hourihane, <alanh@fairlite.demon.co.uk>
24d983712dSmrg *           by: Rainer Keller, <Rainer.Keller@studmail.uni-stuttgart.de>
25d983712dSmrg */
26d983712dSmrg
27d983712dSmrg#ifdef HAVE_CONFIG_H
28d983712dSmrg#include "config.h"
29d983712dSmrg#endif
30d983712dSmrg
31d983712dSmrg#include "tseng.h"
32d983712dSmrg#include "dgaproc.h"
33d983712dSmrg
34d983712dSmrgstatic Bool Tseng_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
35d983712dSmrg				  int *, int *, int *);
36d983712dSmrgstatic Bool Tseng_SetMode(ScrnInfoPtr, DGAModePtr);
37d983712dSmrgstatic void Tseng_Sync(ScrnInfoPtr);
38d983712dSmrgstatic int  Tseng_GetViewport(ScrnInfoPtr);
39d983712dSmrgstatic void Tseng_SetViewport(ScrnInfoPtr, int, int, int);
40d983712dSmrgstatic void Tseng_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
41d983712dSmrgstatic void Tseng_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
42d983712dSmrg/*
43d983712dSmrgstatic void Tseng_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
44d983712dSmrg                                unsigned long);
45d983712dSmrg*/
46d983712dSmrg
47d983712dSmrgstatic
48d983712dSmrgDGAFunctionRec TsengDGAFuncs = {
49d983712dSmrg   Tseng_OpenFramebuffer,
50d983712dSmrg   NULL, /* Tseng_CloseFramebuffer */
51d983712dSmrg   Tseng_SetMode,
52d983712dSmrg   Tseng_SetViewport,
53d983712dSmrg   Tseng_GetViewport,
54d983712dSmrg   Tseng_Sync,
55d983712dSmrg   Tseng_FillRect,
56d983712dSmrg   Tseng_BlitRect,
57d983712dSmrg   NULL  /* Tseng_BlitTransRect */
58d983712dSmrg};
59d983712dSmrg
60d983712dSmrg
61d983712dSmrg
62d983712dSmrg
63d983712dSmrgBool
64d983712dSmrgTsengDGAInit(ScreenPtr pScreen)
65d983712dSmrg{
66d983712dSmrg  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
67d983712dSmrg  TsengPtr pTseng = TsengPTR(pScrn);
68d983712dSmrg  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
69d983712dSmrg  DisplayModePtr pMode, firstMode;
70d983712dSmrg  int Bpp = pScrn->bitsPerPixel >> 3;
71d983712dSmrg  int num = 0;
72d983712dSmrg  int imlines =  (pScrn->videoRam * 1024) /
73d983712dSmrg       (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3));
74d983712dSmrg
75d983712dSmrg  if (!pTseng->DGAnumModes) {
76d983712dSmrg    pMode = firstMode = pScrn->modes;
77d983712dSmrg    while (pMode) {
78d983712dSmrg      newmodes = xrealloc(modes, (num + 1) * sizeof (DGAModeRec));
79d983712dSmrg      if (!newmodes) {
80d983712dSmrg	xfree(modes);
81d983712dSmrg	return FALSE;
82d983712dSmrg      }
83d983712dSmrg      modes = newmodes;
84d983712dSmrg      currentMode = modes + num;
85d983712dSmrg      num++;
86d983712dSmrg      (void)memset(currentMode, 1, sizeof(DGAModeRec));
87d983712dSmrg      currentMode->mode = pMode;
88d983712dSmrg      currentMode->flags = DGA_PIXMAP_AVAILABLE
89d983712dSmrg	  | ((pTseng->UseAccel) ? (DGA_FILL_RECT | DGA_BLIT_RECT) : 0);
90d983712dSmrg      if (pMode->Flags & V_DBLSCAN)
91d983712dSmrg	currentMode->flags |= DGA_DOUBLESCAN;
92d983712dSmrg      if(pMode->Flags & V_INTERLACE)
93d983712dSmrg	currentMode->flags |= DGA_INTERLACED;
94d983712dSmrg      currentMode->byteOrder        = pScrn->imageByteOrder;
95d983712dSmrg      currentMode->depth            = pScrn->depth;
96d983712dSmrg      currentMode->bitsPerPixel     = pScrn->bitsPerPixel;
97d983712dSmrg      currentMode->red_mask         = pScrn->mask.red;
98d983712dSmrg      currentMode->green_mask       = pScrn->mask.green;
99d983712dSmrg      currentMode->blue_mask        = pScrn->mask.blue;
100d983712dSmrg      currentMode->visualClass      = (Bpp == 1) ? PseudoColor : TrueColor;
101d983712dSmrg      currentMode->viewportWidth    = pMode->HDisplay;
102d983712dSmrg      currentMode->viewportHeight   = pMode->VDisplay;
103d983712dSmrg      currentMode->xViewportStep    = 1; /*  The granularity of x and y pos. */
104d983712dSmrg      currentMode->yViewportStep    = 1;
105d983712dSmrg      currentMode->viewportFlags    = 0 /*DGA_FLIP_RETRACE*/;
106d983712dSmrg      currentMode->offset           = 0;
107d983712dSmrg      currentMode->address          = pTseng->FbBase;
108d983712dSmrg      currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L;
109d983712dSmrg      currentMode->pixmapWidth      = currentMode->imageWidth = pScrn->displayWidth;
110d983712dSmrg      currentMode->pixmapHeight     = currentMode->imageHeight = imlines;
111d983712dSmrg      currentMode->maxViewportX     = currentMode->imageWidth -
112d983712dSmrg                                      currentMode->viewportWidth;
113d983712dSmrg      /* this might need to get clamped to some maximum */
114d983712dSmrg      currentMode->maxViewportY     = currentMode->imageHeight -
115d983712dSmrg                                      currentMode->viewportHeight;
116d983712dSmrg
117d983712dSmrg      pMode = pMode->next;
118d983712dSmrg      if(pMode == firstMode)
119d983712dSmrg	break;
120d983712dSmrg    }
121d983712dSmrg    pTseng->DGAnumModes = num;
122d983712dSmrg    pTseng->DGAModes = modes;
123d983712dSmrg  }
124d983712dSmrg  return DGAInit(pScreen, &TsengDGAFuncs, pTseng->DGAModes, pTseng->DGAnumModes);
125d983712dSmrg}
126d983712dSmrg
127d983712dSmrgstatic Bool
128d983712dSmrgTseng_OpenFramebuffer(
129d983712dSmrg   ScrnInfoPtr pScrn,
130d983712dSmrg   char **name,
131d983712dSmrg   unsigned char **mem,
132d983712dSmrg   int *size,
133d983712dSmrg   int *offset,
134d983712dSmrg   int *flags
135d983712dSmrg){
136d983712dSmrg    TsengPtr pTseng = TsengPTR(pScrn);
137d983712dSmrg
138d983712dSmrg    *name = NULL; 		/* no special device */
139d983712dSmrg    *mem = (unsigned char*)pTseng->FbAddress;
140d983712dSmrg    *size = pTseng->FbMapSize;
141d983712dSmrg    *offset = 0;                /* Always */
142d983712dSmrg    *flags = 0;                 /* Root permissions OS-dependent */
143d983712dSmrg
144d983712dSmrg    return TRUE;
145d983712dSmrg}
146d983712dSmrg
147d983712dSmrg
148d983712dSmrgstatic Bool
149d983712dSmrgTseng_SetMode(
150d983712dSmrg   ScrnInfoPtr pScrn,
151d983712dSmrg   DGAModePtr pMode
152d983712dSmrg){
153d983712dSmrg   TsengPtr pTseng = TsengPTR(pScrn);
154d983712dSmrg   static int OldDisplayWidth[MAXSCREENS];
155d983712dSmrg   int index = pScrn->pScreen->myNum;
156d983712dSmrg   Bool ret;
157d983712dSmrg
158d983712dSmrg   if(!pMode) { /* restore the original mode */
159d983712dSmrg	/* put the ScreenParameters back */
160d983712dSmrg	pScrn->displayWidth = OldDisplayWidth[index];
161d983712dSmrg	ret = TsengModeInit(xf86Screens[index], pScrn->currentMode);
162d983712dSmrg	pTseng->DGAactive = FALSE;
163d983712dSmrg   } else {
164d983712dSmrg	if(!pTseng->DGAactive) {  /* save the old parameters */
165d983712dSmrg	    OldDisplayWidth[index] = pScrn->displayWidth;
166d983712dSmrg
167d983712dSmrg	    pTseng->DGAactive = TRUE;
168d983712dSmrg	}
169d983712dSmrg	pScrn->displayWidth = pMode->bytesPerScanline /
170d983712dSmrg			      (pMode->bitsPerPixel >> 3);
171d983712dSmrg
172d983712dSmrg	ret = TsengModeInit(xf86Screens[index], pMode->mode);
173d983712dSmrg   }
174d983712dSmrg   return ret;
175d983712dSmrg}
176d983712dSmrg
177d983712dSmrgstatic void
178d983712dSmrgTseng_SetViewport(
179d983712dSmrg   ScrnInfoPtr pScrn,
180d983712dSmrg   int x, int y,
181d983712dSmrg   int flags
182d983712dSmrg){
183d983712dSmrg   TsengPtr pTseng = TsengPTR(pScrn);
184d983712dSmrg   vgaHWPtr hwp = VGAHWPTR(pScrn);
185d983712dSmrg
186d983712dSmrg   TsengAdjustFrame(pScrn->pScreen->myNum, x, y, flags);
187d983712dSmrg   while((hwp->readST01(hwp) & 0x08));
188d983712dSmrg   while(!(hwp->readST01(hwp) & 0x08));
189d983712dSmrg
190d983712dSmrg   pTseng->DGAViewportStatus = 0;  /* TsengAdjustFrame loops until finished */
191d983712dSmrg}
192d983712dSmrg
193d983712dSmrgstatic int
194d983712dSmrgTseng_GetViewport(
195d983712dSmrg  ScrnInfoPtr pScrn
196d983712dSmrg){
197d983712dSmrg    TsengPtr pTseng = TsengPTR(pScrn);
198d983712dSmrg
199d983712dSmrg    return pTseng->DGAViewportStatus;
200d983712dSmrg}
201d983712dSmrg
202d983712dSmrg
203d983712dSmrg
204d983712dSmrgstatic void
205d983712dSmrgTseng_Sync(
206d983712dSmrg   ScrnInfoPtr pScrn
207d983712dSmrg){
208d983712dSmrg    TsengPtr pTseng = TsengPTR(pScrn);
209d983712dSmrg
210d983712dSmrg    if(pTseng->AccelInfoRec) {
211d983712dSmrg	(*pTseng->AccelInfoRec->Sync)(pScrn);
212d983712dSmrg    }
213d983712dSmrg}
214d983712dSmrg
215d983712dSmrgstatic void
216d983712dSmrgTseng_FillRect (
217d983712dSmrg   ScrnInfoPtr pScrn,
218d983712dSmrg   int x, int y, int w, int h,
219d983712dSmrg   unsigned long color
220d983712dSmrg){
221d983712dSmrg    TsengPtr pTseng = TsengPTR(pScrn);
222d983712dSmrg
223d983712dSmrg    if(pTseng->AccelInfoRec) {
224d983712dSmrg	(*pTseng->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
225d983712dSmrg	(*pTseng->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
226d983712dSmrg	SET_SYNC_FLAG(pTseng->AccelInfoRec);
227d983712dSmrg    }
228d983712dSmrg}
229d983712dSmrg
230d983712dSmrgstatic void
231d983712dSmrgTseng_BlitRect(
232d983712dSmrg   ScrnInfoPtr pScrn,
233d983712dSmrg   int srcx, int srcy,
234d983712dSmrg   int w, int h,
235d983712dSmrg   int dstx, int dsty
236d983712dSmrg){
237d983712dSmrg    TsengPtr pTseng = TsengPTR(pScrn);
238d983712dSmrg
239d983712dSmrg    if(pTseng->AccelInfoRec) {
240d983712dSmrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
241d983712dSmrg	int ydir = (srcy < dsty) ? -1 : 1;
242d983712dSmrg
243d983712dSmrg	(*pTseng->AccelInfoRec->SetupForScreenToScreenCopy)(
244d983712dSmrg		pScrn, xdir, ydir, GXcopy, ~0, -1);
245d983712dSmrg	(*pTseng->AccelInfoRec->SubsequentScreenToScreenCopy)(
246d983712dSmrg		pScrn, srcx, srcy, dstx, dsty, w, h);
247d983712dSmrg	SET_SYNC_FLAG(pTseng->AccelInfoRec);
248d983712dSmrg    }
249d983712dSmrg}
250