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