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