atidga.c revision 1b12faf6
1/*
2 * Copyright 2000 through 2004 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
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 copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of Marc Aurele La France not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  Marc Aurele La France 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 * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
16 * EVENT SHALL MARC AURELE LA FRANCE 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
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26#ifndef AVOID_DGA
27
28#include <string.h>
29
30#include "ati.h"
31#include "atiadjust.h"
32#include "atichip.h"
33#include "atidac.h"
34#include "atidga.h"
35#include "atimode.h"
36#include "atistruct.h"
37
38#include "dgaproc.h"
39
40/*
41 * ATIDGAOpenFramebuffer --
42 *
43 * This function returns various framebuffer attributes to a DGA client.
44 */
45static Bool
46ATIDGAOpenFramebuffer
47(
48    ScrnInfoPtr   pScreenInfo,
49    char          **DeviceName,
50    unsigned char **ApertureBase,
51    int           *ApertureSize,
52    int           *ApertureOffset,
53    int           *flags
54)
55{
56    ATIPtr pATI = ATIPTR(pScreenInfo);
57
58    *DeviceName = NULL;         /* No special device */
59    *ApertureBase = (unsigned char *)(pATI->LinearBase);
60    *ApertureSize = pScreenInfo->videoRam * 1024;
61    *ApertureOffset = 0;        /* Always */
62    *flags = 0;                 /* Root premissions OS-dependent */
63
64    return TRUE;
65}
66
67static int
68BitsSet
69(
70    unsigned long data
71)
72{
73    unsigned long mask = 1;
74    int           set  = 0;
75
76    for (;  mask;  mask <<= 1)
77        if (data & mask)
78            set++;
79
80    return set;
81}
82
83/*
84 * ATIDGASetMode --
85 *
86 * This function sets a graphics mode for a DGA client.
87 */
88static Bool
89ATIDGASetMode
90(
91    ScrnInfoPtr pScreenInfo,
92    DGAModePtr  pDGAMode
93)
94{
95    ATIPtr         pATI    = ATIPTR(pScreenInfo);
96    DisplayModePtr pMode;
97    int            iScreen = pScreenInfo->scrnIndex;
98    int            frameX0, frameY0;
99
100    if (pDGAMode)
101    {
102        pMode = pDGAMode->mode;
103        pATI->depth = pDGAMode->depth;
104        pATI->bitsPerPixel = pDGAMode->bitsPerPixel;
105        pATI->displayWidth =
106            pDGAMode->bytesPerScanline * 8 / pATI->bitsPerPixel;
107        pATI->weight.red = BitsSet(pDGAMode->red_mask);
108        pATI->weight.green = BitsSet(pDGAMode->green_mask);
109        pATI->weight.blue = BitsSet(pDGAMode->blue_mask);
110        frameX0 = frameY0 = 0;
111        if (!pATI->currentMode)
112            pATI->currentMode = pScreenInfo->currentMode;
113    }
114    else
115    {
116        if (!(pMode = pATI->currentMode))
117            return TRUE;
118
119        pATI->depth = pScreenInfo->depth;
120        pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
121        pATI->displayWidth = pScreenInfo->displayWidth;
122        pATI->weight = pScreenInfo->weight;
123        frameX0 = pScreenInfo->frameX0;
124        frameY0 = pScreenInfo->frameY0;
125    }
126
127    pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
128    ATIAdjustPreInit(pATI);
129    ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
130
131    if (!(*pScreenInfo->SwitchMode)(iScreen, pMode, 0))
132        return FALSE;
133    if (!pDGAMode)
134        pATI->currentMode = NULL;
135    (*pScreenInfo->AdjustFrame)(iScreen, frameX0, frameY0, 0);
136
137    return TRUE;
138}
139
140/*
141 * ATIDGASetViewport --
142 *
143 * This function sets the display start address for a DGA client.
144 */
145static void
146ATIDGASetViewport
147(
148    ScrnInfoPtr pScreenInfo,
149    int         x,
150    int         y,
151    int         flags
152)
153{
154    (*pScreenInfo->AdjustFrame)(pScreenInfo->pScreen->myNum, x, y, flags);
155}
156
157/*
158 * ATIDGAGetViewport --
159 *
160 * This function returns the current status of prior DGA requests to set the
161 * adapter's display start address.
162 */
163static int
164ATIDGAGetViewport
165(
166    ScrnInfoPtr pScreenInfo
167)
168{
169    return 0;   /* There are never any pending requests */
170}
171
172/*
173 * ATIDGAFillRect --
174 *
175 * This function calls XAA solid fill primitives to fill a rectangle.
176 */
177static void
178ATIDGAFillRect
179(
180    ScrnInfoPtr   pScreenInfo,
181    int           x,
182    int           y,
183    int           w,
184    int           h,
185    unsigned long colour
186)
187{
188    ATIPtr        pATI     = ATIPTR(pScreenInfo);
189/*FIXME : use EXA if available */
190#ifdef USE_XAA
191    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
192
193    (*pXAAInfo->SetupForSolidFill)(pScreenInfo, (int)colour, GXcopy,
194                                   (CARD32)(~0));
195    (*pXAAInfo->SubsequentSolidFillRect)(pScreenInfo, x, y, w, h);
196
197    if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
198        SET_SYNC_FLAG(pXAAInfo);
199#endif
200}
201
202/*
203 * ATIDGABlitRect --
204 *
205 * This function calls XAA screen-to-screen copy primitives to copy a
206 * rectangle.
207 */
208static void
209ATIDGABlitRect
210(
211    ScrnInfoPtr pScreenInfo,
212    int         xSrc,
213    int         ySrc,
214    int         w,
215    int         h,
216    int         xDst,
217    int         yDst
218)
219{
220    ATIPtr        pATI     = ATIPTR(pScreenInfo);
221/*FIXME : use EXA if available */
222#ifdef USE_XAA
223    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
224    int           xdir     = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1;
225    int           ydir     = (ySrc < yDst) ? -1 : 1;
226
227    (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo,
228        xdir, ydir, GXcopy, (CARD32)(~0), -1);
229    (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
230        xSrc, ySrc, xDst, yDst, w, h);
231
232    if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
233        SET_SYNC_FLAG(pXAAInfo);
234#endif
235}
236
237/*
238 * ATIDGABlitTransRect --
239 *
240 * This function calls XAA screen-to-screen copy primitives to transparently
241 * copy a rectangle.
242 */
243static void
244ATIDGABlitTransRect
245(
246    ScrnInfoPtr   pScreenInfo,
247    int           xSrc,
248    int           ySrc,
249    int           w,
250    int           h,
251    int           xDst,
252    int           yDst,
253    unsigned long colour
254)
255{
256    ATIPtr        pATI     = ATIPTR(pScreenInfo);
257/*FIXME : use EXA if available */
258#ifdef USE_XAA
259    XAAInfoRecPtr pXAAInfo = pATI->pXAAInfo;
260    int           xdir     = ((xSrc < xDst) && (ySrc == yDst)) ? -1 : 1;
261    int           ydir     = (ySrc < yDst) ? -1 : 1;
262
263    pATI->XAAForceTransBlit = TRUE;
264
265    (*pXAAInfo->SetupForScreenToScreenCopy)(pScreenInfo,
266        xdir, ydir, GXcopy, (CARD32)(~0), (int)colour);
267
268    pATI->XAAForceTransBlit = FALSE;
269
270    (*pXAAInfo->SubsequentScreenToScreenCopy)(pScreenInfo,
271        xSrc, ySrc, xDst, yDst, w, h);
272
273    if (pScreenInfo->bitsPerPixel == pATI->bitsPerPixel)
274        SET_SYNC_FLAG(pXAAInfo);
275#endif
276}
277
278/*
279 * ATIDGAAddModes --
280 *
281 * This function translates DisplayModeRec's into DGAModeRec's.
282 */
283static void
284ATIDGAAddModes
285(
286    ScrnInfoPtr pScreenInfo,
287    ATIPtr      pATI,
288    int         flags,
289    int         depth,
290    int         bitsPerPixel,
291    int         redMask,
292    int         greenMask,
293    int         blueMask,
294    int         visualClass
295)
296{
297    DisplayModePtr pMode         = pScreenInfo->modes;
298    DGAModePtr     pDGAMode;
299    int            displayWidth  = pScreenInfo->displayWidth;
300    int            videoBits     = pScreenInfo->videoRam * 1024 * 8;
301    int            xViewportStep = 64 / UnitOf(bitsPerPixel);
302    int            modePitch, bitsPerScanline, maxViewportY;
303
304    if (bitsPerPixel != pScreenInfo->bitsPerPixel)
305        displayWidth = 0;
306
307    while (1)
308    {
309        /* Weed out multiscanned modes */
310        if ((pMode->VScan <= 1) ||
311            ((pMode->VScan == 2) && !(pMode->Flags & V_DBLSCAN)))
312        {
313            /*
314             * For code simplicity, ensure DGA mode pitch is a multiple of 64
315             * bytes.
316             */
317            if (!(modePitch = displayWidth))
318            {
319                modePitch = ((64 * 8) / UnitOf(bitsPerPixel)) - 1;
320                modePitch = (pMode->HDisplay + modePitch) & ~modePitch;
321            }
322
323            /* Ensure the mode fits in video memory */
324            if ((modePitch * bitsPerPixel * pMode->VDisplay) <= videoBits)
325            {
326                /* Stop generating modes on out-of-memory conditions */
327                pDGAMode = realloc(pATI->pDGAMode,
328                    (pATI->nDGAMode + 1) * SizeOf(DGAModeRec));
329                if (!pDGAMode)
330                    break;
331
332                pATI->pDGAMode = pDGAMode;
333                pDGAMode += pATI->nDGAMode;
334                pATI->nDGAMode++;
335                (void)memset(pDGAMode, 0, SizeOf(DGAModeRec));
336
337                /* Fill in the mode structure */
338                pDGAMode->mode = pMode;
339                pDGAMode->flags = flags;
340                if (bitsPerPixel == pScreenInfo->bitsPerPixel)
341                {
342                    pDGAMode->flags |= DGA_PIXMAP_AVAILABLE;
343                    pDGAMode->address = pATI->pMemory;
344
345#ifdef USE_XAA
346                    if (pATI->pXAAInfo)
347                        pDGAMode->flags &= ~DGA_CONCURRENT_ACCESS;
348#endif
349                }
350                if ((pMode->Flags & V_DBLSCAN) || (pMode->VScan > 1))
351                    pDGAMode->flags |= DGA_DOUBLESCAN;
352                if (pMode->Flags & V_INTERLACE)
353                    pDGAMode->flags |= DGA_INTERLACED;
354
355                pDGAMode->byteOrder = pScreenInfo->imageByteOrder;
356                pDGAMode->depth = depth;
357                pDGAMode->bitsPerPixel = bitsPerPixel;
358                pDGAMode->red_mask = redMask;
359                pDGAMode->green_mask = greenMask;
360                pDGAMode->blue_mask = blueMask;
361                pDGAMode->visualClass = visualClass;
362
363                pDGAMode->viewportWidth = pMode->HDisplay;
364                pDGAMode->viewportHeight = pMode->VDisplay;
365                pDGAMode->xViewportStep = xViewportStep;
366                pDGAMode->yViewportStep = 1;
367
368                bitsPerScanline = modePitch * bitsPerPixel;
369                pDGAMode->bytesPerScanline = bitsPerScanline / 8;
370                pDGAMode->imageWidth = pDGAMode->pixmapWidth = modePitch;
371                pDGAMode->imageHeight = pDGAMode->pixmapHeight =
372                    videoBits / bitsPerScanline;
373
374                pDGAMode->maxViewportX =
375                    pDGAMode->imageWidth - pDGAMode->viewportWidth;
376                pDGAMode->maxViewportY =
377                    pDGAMode->imageHeight - pDGAMode->viewportHeight;
378                maxViewportY =
379                    ((((pATI->AdjustMaxBase * 8) / bitsPerPixel) +
380                      xViewportStep) / modePitch) - 1;
381                if (maxViewportY < pDGAMode->maxViewportY)
382                    pDGAMode->maxViewportY = maxViewportY;
383            }
384        }
385
386        if ((pMode = pMode->next) == pScreenInfo->modes)
387        {
388            if (!displayWidth)
389                break;
390
391            displayWidth = 0;
392        }
393    }
394}
395
396/*
397 * ATIDGAInit --
398 *
399 * This function initialises the driver's support for the DGA extension.
400 */
401Bool
402ATIDGAInit
403(
404    ScreenPtr   pScreen,
405    ScrnInfoPtr pScreenInfo,
406    ATIPtr      pATI
407)
408{
409#ifdef USE_XAA
410    XAAInfoRecPtr pXAAInfo;
411#endif
412    int           flags;
413
414    if (!pATI->nDGAMode)
415    {
416        /* Set up DGA callbacks */
417        pATI->ATIDGAFunctions.OpenFramebuffer = ATIDGAOpenFramebuffer;
418        pATI->ATIDGAFunctions.SetMode         = ATIDGASetMode;
419        pATI->ATIDGAFunctions.SetViewport     = ATIDGASetViewport;
420        pATI->ATIDGAFunctions.GetViewport     = ATIDGAGetViewport;
421
422        flags = 0;
423#ifdef USE_XAA
424        if ((pXAAInfo = pATI->pXAAInfo))
425        {
426            pATI->ATIDGAFunctions.Sync = pXAAInfo->Sync;
427            if (pXAAInfo->SetupForSolidFill &&
428                pXAAInfo->SubsequentSolidFillRect)
429            {
430                flags |= DGA_FILL_RECT;
431                pATI->ATIDGAFunctions.FillRect = ATIDGAFillRect;
432            }
433            if (pXAAInfo->SetupForScreenToScreenCopy &&
434                pXAAInfo->SubsequentScreenToScreenCopy)
435            {
436                flags |= DGA_BLIT_RECT | DGA_BLIT_RECT_TRANS;
437                pATI->ATIDGAFunctions.BlitRect      = ATIDGABlitRect;
438                pATI->ATIDGAFunctions.BlitTransRect = ATIDGABlitTransRect;
439            }
440        }
441#endif
442        if (!flags)
443            flags = DGA_CONCURRENT_ACCESS;
444
445        ATIDGAAddModes(pScreenInfo, pATI, flags,
446            8, 8, 0, 0, 0, PseudoColor);
447
448        if ((pATI->Chip >= ATI_CHIP_264CT))
449        {
450            ATIDGAAddModes(pScreenInfo, pATI, flags,
451                15, 16, 0x7C00U, 0x03E0U, 0x001FU, TrueColor);
452
453            ATIDGAAddModes(pScreenInfo, pATI, flags,
454                16, 16, 0xF800U, 0x07E0U, 0x001FU, TrueColor);
455
456            ATIDGAAddModes(pScreenInfo, pATI, flags,
457                24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor);
458
459            ATIDGAAddModes(pScreenInfo, pATI, flags,
460                24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, TrueColor);
461
462            if (pATI->DAC != ATI_DAC_INTERNAL)      /* Not first revision */
463            {
464                ATIDGAAddModes(pScreenInfo, pATI, flags,
465                    15, 16, 0x7C00U, 0x03E0U, 0x001FU, DirectColor);
466
467                ATIDGAAddModes(pScreenInfo, pATI, flags,
468                    16, 16, 0xF800U, 0x07E0U, 0x001FU, DirectColor);
469
470                ATIDGAAddModes(pScreenInfo, pATI, flags,
471                    24, 24, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor);
472
473                ATIDGAAddModes(pScreenInfo, pATI, flags,
474                    24, 32, 0x00FF0000U, 0x0000FF00U, 0x000000FFU, DirectColor);
475            }
476        }
477    }
478
479    return DGAInit(pScreen, &pATI->ATIDGAFunctions, pATI->pDGAMode,
480                   pATI->nDGAMode);
481}
482
483#endif /* AVOID_DGA */
484