i740_dga.c revision 34d2f1a1
1/*
2 * Copyright 2001 by Patrick LERDA
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 Patrick LERDA not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Patrick LERDA 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 * PATRICK LERDA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL PATRICK LERDA 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:  Patrick LERDA
23 */
24
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "xf86.h"
30#include "xf86_OSproc.h"
31#include "xf86Pci.h"
32#include "xf86PciInfo.h"
33#include "vgaHW.h"
34#include "xf86xv.h"
35#include "i740.h"
36#ifdef HAVE_XAA_H
37#include "xaalocal.h"
38#endif
39#include "dgaproc.h"
40#include "i740_dga.h"
41
42static Bool I740_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, int *, int *, int *);
43static Bool I740_SetMode(ScrnInfoPtr, DGAModePtr);
44static int  I740_GetViewport(ScrnInfoPtr);
45static void I740_SetViewport(ScrnInfoPtr, int, int, int);
46#ifdef HAVE_XAA_H
47static void I740_Sync(ScrnInfoPtr);
48static void I740_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
49static void I740_BlitRect(ScrnInfoPtr, int, int, int, int, int, int);
50#if 0
51static void I740_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, unsigned long);
52#endif
53#endif
54static DGAFunctionRec I740DGAFuncs = {
55   I740_OpenFramebuffer,
56   NULL,
57   I740_SetMode,
58   I740_SetViewport,
59   I740_GetViewport,
60#ifdef HAVE_XAA_H
61   I740_Sync,
62   I740_FillRect,
63   I740_BlitRect,
64#if 0
65   I740_BlitTransRect
66#else
67   NULL
68#endif
69#else
70   NULL, NULL, NULL
71#endif
72};
73
74Bool I740DGAInit(ScreenPtr pScreen)
75{
76  ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
77  I740Ptr pI740 = I740PTR(pScrn);
78  DGAModePtr modes = NULL, newmodes = NULL, currentMode;
79  DisplayModePtr pMode, firstMode;
80  int Bpp = pScrn->bitsPerPixel >> 3;
81  int num = 0;
82
83  pMode = firstMode = pScrn->modes;
84
85  while(pMode) {
86
87    newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec));
88
89    if(!newmodes) {
90      free(modes);
91      return FALSE;
92    }
93    modes = newmodes;
94
95    currentMode = modes + num;
96    num++;
97
98    currentMode->mode = pMode;
99    currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE;
100#ifdef HAVE_XAA_H
101    if(pI740->AccelInfoRec)
102      currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
103#endif
104    if(pMode->Flags & V_DBLSCAN)
105      currentMode->flags |= DGA_DOUBLESCAN;
106    if(pMode->Flags & V_INTERLACE)
107      currentMode->flags |= DGA_INTERLACED;
108    currentMode->byteOrder = pScrn->imageByteOrder;
109    currentMode->depth = pScrn->depth;
110    currentMode->bitsPerPixel = pScrn->bitsPerPixel;
111    currentMode->red_mask = pScrn->mask.red;
112    currentMode->green_mask = pScrn->mask.green;
113    currentMode->blue_mask = pScrn->mask.blue;
114    currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor;
115    currentMode->viewportWidth = pMode->HDisplay;
116    currentMode->viewportHeight = pMode->VDisplay;
117    currentMode->xViewportStep = (Bpp == 3) ? 2 : 1;
118    currentMode->yViewportStep = 1;
119    currentMode->viewportFlags = DGA_FLIP_RETRACE;
120    currentMode->offset = 0;
121    currentMode->address = pI740->FbBase;
122
123    currentMode->bytesPerScanline =
124      ((pScrn->displayWidth * Bpp) + 3) & ~3L;
125    currentMode->imageWidth = pI740->FbMemBox.x2;
126    currentMode->imageHeight =  pI740->FbMemBox.y2;
127    currentMode->pixmapWidth = currentMode->imageWidth;
128    currentMode->pixmapHeight = currentMode->imageHeight;
129    currentMode->maxViewportX = currentMode->imageWidth -
130      currentMode->viewportWidth;
131    /* this might need to get clamped to some maximum */
132    currentMode->maxViewportY = currentMode->imageHeight -
133      currentMode->viewportHeight;
134
135    pMode = pMode->next;
136    if(pMode == firstMode)
137      break;
138  }
139
140  pI740->numDGAModes = num;
141  pI740->DGAModes = modes;
142
143  return DGAInit(pScreen, &I740DGAFuncs, modes, num);
144}
145
146static DisplayModePtr I740SavedDGAModes[MAXSCREENS];
147
148static Bool I740_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
149{
150  int index = pScrn->pScreen->myNum;
151  I740Ptr pI740 = I740PTR(pScrn);
152
153  if(!pMode) { /* restore the original mode */
154    if(pI740->DGAactive) {
155      pScrn->currentMode = I740SavedDGAModes[index];
156      I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
157      I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, 0, 0));
158      pI740->DGAactive = FALSE;
159    }
160  } else {
161    if(!pI740->DGAactive) {
162      I740SavedDGAModes[index] = pScrn->currentMode;
163      pI740->DGAactive = TRUE;
164    }
165
166    I740SwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
167  }
168
169  return TRUE;
170}
171
172static int I740_GetViewport(ScrnInfoPtr pScrn)
173{
174  I740Ptr pI740 = I740PTR(pScrn);
175
176  return pI740->DGAViewportStatus;
177}
178
179static void I740_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags)
180{
181  I740Ptr pI740 = I740PTR(pScrn);
182  vgaHWPtr hwp = VGAHWPTR(pScrn);
183
184  I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
185
186  /* wait for retrace */
187  while((hwp->readST01(hwp) & 0x08));
188  while(!(hwp->readST01(hwp) & 0x08));
189
190  pI740->DGAViewportStatus = 0;
191}
192
193#ifdef HAVE_XAA_H
194static void I740_FillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, unsigned long color)
195{
196  I740Ptr pI740 = I740PTR(pScrn);
197
198  if(pI740->AccelInfoRec) {
199    (*pI740->AccelInfoRec->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
200    (*pI740->AccelInfoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
201    SET_SYNC_FLAG(pI740->AccelInfoRec);
202  }
203}
204
205static void I740_Sync(ScrnInfoPtr pScrn)
206{
207  I740Ptr pI740 = I740PTR(pScrn);
208
209  if(pI740->AccelInfoRec) {
210    (*pI740->AccelInfoRec->Sync)(pScrn);
211  }
212}
213
214static void I740_BlitRect(
215   ScrnInfoPtr pScrn,
216   int srcx, int srcy,
217   int w, int h,
218   int dstx, int dsty
219   ){
220  I740Ptr pI740 = I740PTR(pScrn);
221
222  if(pI740->AccelInfoRec) {
223    int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
224    int ydir = (srcy < dsty) ? -1 : 1;
225
226    (*pI740->AccelInfoRec->SetupForScreenToScreenCopy)(pScrn, xdir, ydir, GXcopy, ~0, -1);
227    (*pI740->AccelInfoRec->SubsequentScreenToScreenCopy)(pScrn, srcx, srcy, dstx, dsty, w, h);
228    SET_SYNC_FLAG(pI740->AccelInfoRec);
229  }
230}
231#endif
232#if 0
233static void I740_BlitTransRect(ScrnInfoPtr pScrn,
234			       int srcx, int srcy,
235			       int w, int h,
236			       int dstx, int dsty,
237			       unsigned long color
238			       )
239{
240  /* this one should be separate since the XAA function would
241     prohibit usage of ~0 as the key */
242}
243#endif
244
245static Bool I740_OpenFramebuffer(
246				 ScrnInfoPtr pScrn,
247				 char **name,
248				 unsigned char **mem,
249				 int *size,
250				 int *offset,
251				 int *flags
252				 ){
253    I740Ptr pI740 = I740PTR(pScrn);
254
255    *name = NULL; 		/* no special device */
256    *mem = (unsigned char*)pI740->LinearAddr;
257    *size = pI740->FbMapSize;
258    *offset = 0;
259    *flags = DGA_NEED_ROOT;
260
261    return TRUE;
262}
263