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