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