xf86DGA.c revision 35c4bbdf
1/*
2 * Copyright (c) 1995  Jon Tombs
3 * Copyright (c) 1995, 1996, 1999  XFree86 Inc
4 * Copyright (c) 1998-2002 by The XFree86 Project, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Except as contained in this notice, the name of the copyright holder(s)
25 * and author(s) shall not be used in advertising or otherwise to promote
26 * the sale, use or other dealings in this Software without prior written
27 * authorization from the copyright holder(s) and author(s).
28 *
29 * Written by Mark Vojkovich
30 */
31
32/*
33 * This is quite literally just two files glued together:
34 * hw/xfree86/common/xf86DGA.c is the first part, and
35 * hw/xfree86/dixmods/extmod/xf86dga2.c is the second part.  One day, if
36 * someone actually cares about DGA, it'd be nice to clean this up.  But trust
37 * me, I am not that person.
38 */
39
40#ifdef HAVE_XORG_CONFIG_H
41#include <xorg-config.h>
42#endif
43
44#include <X11/X.h>
45#include <X11/Xproto.h>
46#include "xf86.h"
47#include "xf86str.h"
48#include "xf86Priv.h"
49#include "dgaproc.h"
50#include <X11/extensions/xf86dgaproto.h>
51#include "colormapst.h"
52#include "pixmapstr.h"
53#include "inputstr.h"
54#include "globals.h"
55#include "servermd.h"
56#include "micmap.h"
57#include "xkbsrv.h"
58#include "xf86Xinput.h"
59#include "exglobals.h"
60#include "exevents.h"
61#include "eventstr.h"
62#include "eventconvert.h"
63#include "xf86Extensions.h"
64
65#include "mi.h"
66
67#include "misc.h"
68#include "dixstruct.h"
69#include "dixevents.h"
70#include "extnsionst.h"
71#include "cursorstr.h"
72#include "scrnintstr.h"
73#include "swaprep.h"
74#include "dgaproc.h"
75#include "protocol-versions.h"
76
77#include <string.h>
78
79#define DGA_PROTOCOL_OLD_SUPPORT 1
80
81static DevPrivateKeyRec DGAScreenKeyRec;
82
83#define DGAScreenKeyRegistered dixPrivateKeyRegistered(&DGAScreenKeyRec)
84static Bool mieq_installed;
85
86static Bool DGACloseScreen(ScreenPtr pScreen);
87static void DGADestroyColormap(ColormapPtr pmap);
88static void DGAInstallColormap(ColormapPtr pmap);
89static void DGAUninstallColormap(ColormapPtr pmap);
90static void DGAHandleEvent(int screen_num, InternalEvent *event,
91                           DeviceIntPtr device);
92
93static void
94 DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode);
95
96static unsigned char DGAReqCode = 0;
97static int DGAErrorBase;
98static int DGAEventBase;
99
100#define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \
101    dixLookupPrivate(&(pScreen)->devPrivates, &DGAScreenKeyRec))
102
103typedef struct _FakedVisualList {
104    Bool free;
105    VisualPtr pVisual;
106    struct _FakedVisualList *next;
107} FakedVisualList;
108
109typedef struct {
110    ScrnInfoPtr pScrn;
111    int numModes;
112    DGAModePtr modes;
113    CloseScreenProcPtr CloseScreen;
114    DestroyColormapProcPtr DestroyColormap;
115    InstallColormapProcPtr InstallColormap;
116    UninstallColormapProcPtr UninstallColormap;
117    DGADevicePtr current;
118    DGAFunctionPtr funcs;
119    int input;
120    ClientPtr client;
121    int pixmapMode;
122    FakedVisualList *fakedVisuals;
123    ColormapPtr dgaColormap;
124    ColormapPtr savedColormap;
125    Bool grabMouse;
126    Bool grabKeyboard;
127} DGAScreenRec, *DGAScreenPtr;
128
129Bool
130DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, DGAModePtr modes, int num)
131{
132    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
133    DGAScreenPtr pScreenPriv;
134    int i;
135
136    if (!funcs || !funcs->SetMode || !funcs->OpenFramebuffer)
137        return FALSE;
138
139    if (!modes || num <= 0)
140        return FALSE;
141
142    if (!dixRegisterPrivateKey(&DGAScreenKeyRec, PRIVATE_SCREEN, 0))
143        return FALSE;
144
145    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
146
147    if (!pScreenPriv) {
148        if (!(pScreenPriv = (DGAScreenPtr) malloc(sizeof(DGAScreenRec))))
149            return FALSE;
150        dixSetPrivate(&pScreen->devPrivates, &DGAScreenKeyRec, pScreenPriv);
151        pScreenPriv->CloseScreen = pScreen->CloseScreen;
152        pScreen->CloseScreen = DGACloseScreen;
153        pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
154        pScreen->DestroyColormap = DGADestroyColormap;
155        pScreenPriv->InstallColormap = pScreen->InstallColormap;
156        pScreen->InstallColormap = DGAInstallColormap;
157        pScreenPriv->UninstallColormap = pScreen->UninstallColormap;
158        pScreen->UninstallColormap = DGAUninstallColormap;
159    }
160
161    pScreenPriv->pScrn = pScrn;
162    pScreenPriv->numModes = num;
163    pScreenPriv->modes = modes;
164    pScreenPriv->current = NULL;
165
166    pScreenPriv->funcs = funcs;
167    pScreenPriv->input = 0;
168    pScreenPriv->client = NULL;
169    pScreenPriv->fakedVisuals = NULL;
170    pScreenPriv->dgaColormap = NULL;
171    pScreenPriv->savedColormap = NULL;
172    pScreenPriv->grabMouse = FALSE;
173    pScreenPriv->grabKeyboard = FALSE;
174
175    for (i = 0; i < num; i++)
176        modes[i].num = i + 1;
177
178#ifdef PANORAMIX
179    if (!noPanoramiXExtension)
180        for (i = 0; i < num; i++)
181            modes[i].flags &= ~DGA_PIXMAP_AVAILABLE;
182#endif
183
184    return TRUE;
185}
186
187/* DGAReInitModes allows the driver to re-initialize
188 * the DGA mode list.
189 */
190
191Bool
192DGAReInitModes(ScreenPtr pScreen, DGAModePtr modes, int num)
193{
194    DGAScreenPtr pScreenPriv;
195    int i;
196
197    /* No DGA? Ignore call (but don't make it look like it failed) */
198    if (!DGAScreenKeyRegistered)
199        return TRUE;
200
201    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
202
203    /* Same as above */
204    if (!pScreenPriv)
205        return TRUE;
206
207    /* Can't do this while DGA is active */
208    if (pScreenPriv->current)
209        return FALSE;
210
211    /* Quick sanity check */
212    if (!num)
213        modes = NULL;
214    else if (!modes)
215        num = 0;
216
217    pScreenPriv->numModes = num;
218    pScreenPriv->modes = modes;
219
220    /* This practically disables DGA. So be it. */
221    if (!num)
222        return TRUE;
223
224    for (i = 0; i < num; i++)
225        modes[i].num = i + 1;
226
227#ifdef PANORAMIX
228    if (!noPanoramiXExtension)
229        for (i = 0; i < num; i++)
230            modes[i].flags &= ~DGA_PIXMAP_AVAILABLE;
231#endif
232
233    return TRUE;
234}
235
236static void
237FreeMarkedVisuals(ScreenPtr pScreen)
238{
239    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
240    FakedVisualList *prev, *curr, *tmp;
241
242    if (!pScreenPriv->fakedVisuals)
243        return;
244
245    prev = NULL;
246    curr = pScreenPriv->fakedVisuals;
247
248    while (curr) {
249        if (curr->free) {
250            tmp = curr;
251            curr = curr->next;
252            if (prev)
253                prev->next = curr;
254            else
255                pScreenPriv->fakedVisuals = curr;
256            free(tmp->pVisual);
257            free(tmp);
258        }
259        else {
260            prev = curr;
261            curr = curr->next;
262        }
263    }
264}
265
266static Bool
267DGACloseScreen(ScreenPtr pScreen)
268{
269    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
270
271    if (mieq_installed) {
272        mieqSetHandler(ET_DGAEvent, NULL);
273        mieq_installed = FALSE;
274    }
275
276    FreeMarkedVisuals(pScreen);
277
278    pScreen->CloseScreen = pScreenPriv->CloseScreen;
279    pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
280    pScreen->InstallColormap = pScreenPriv->InstallColormap;
281    pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
282
283    /* DGAShutdown() should have ensured that no DGA
284       screen were active by here */
285
286    free(pScreenPriv);
287
288    return ((*pScreen->CloseScreen) (pScreen));
289}
290
291static void
292DGADestroyColormap(ColormapPtr pmap)
293{
294    ScreenPtr pScreen = pmap->pScreen;
295    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
296    VisualPtr pVisual = pmap->pVisual;
297
298    if (pScreenPriv->fakedVisuals) {
299        FakedVisualList *curr = pScreenPriv->fakedVisuals;
300
301        while (curr) {
302            if (curr->pVisual == pVisual) {
303                /* We can't get rid of them yet since FreeColormap
304                   still needs the pVisual during the cleanup */
305                curr->free = TRUE;
306                break;
307            }
308            curr = curr->next;
309        }
310    }
311
312    if (pScreenPriv->DestroyColormap) {
313        pScreen->DestroyColormap = pScreenPriv->DestroyColormap;
314        (*pScreen->DestroyColormap) (pmap);
315        pScreen->DestroyColormap = DGADestroyColormap;
316    }
317}
318
319static void
320DGAInstallColormap(ColormapPtr pmap)
321{
322    ScreenPtr pScreen = pmap->pScreen;
323    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
324
325    if (pScreenPriv->current && pScreenPriv->dgaColormap) {
326        if (pmap != pScreenPriv->dgaColormap) {
327            pScreenPriv->savedColormap = pmap;
328            pmap = pScreenPriv->dgaColormap;
329        }
330    }
331
332    pScreen->InstallColormap = pScreenPriv->InstallColormap;
333    (*pScreen->InstallColormap) (pmap);
334    pScreen->InstallColormap = DGAInstallColormap;
335}
336
337static void
338DGAUninstallColormap(ColormapPtr pmap)
339{
340    ScreenPtr pScreen = pmap->pScreen;
341    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
342
343    if (pScreenPriv->current && pScreenPriv->dgaColormap) {
344        if (pmap == pScreenPriv->dgaColormap) {
345            pScreenPriv->dgaColormap = NULL;
346        }
347    }
348
349    pScreen->UninstallColormap = pScreenPriv->UninstallColormap;
350    (*pScreen->UninstallColormap) (pmap);
351    pScreen->UninstallColormap = DGAUninstallColormap;
352}
353
354int
355xf86SetDGAMode(ScrnInfoPtr pScrn, int num, DGADevicePtr devRet)
356{
357    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
358    DGAScreenPtr pScreenPriv;
359    DGADevicePtr device;
360    PixmapPtr pPix = NULL;
361    DGAModePtr pMode = NULL;
362
363    /* First check if DGAInit was successful on this screen */
364    if (!DGAScreenKeyRegistered)
365        return BadValue;
366    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
367    if (!pScreenPriv)
368        return BadValue;
369
370    if (!num) {
371        if (pScreenPriv->current) {
372            PixmapPtr oldPix = pScreenPriv->current->pPix;
373
374            if (oldPix) {
375                if (oldPix->drawable.id)
376                    FreeResource(oldPix->drawable.id, RT_NONE);
377                else
378                    (*pScreen->DestroyPixmap) (oldPix);
379            }
380            free(pScreenPriv->current);
381            pScreenPriv->current = NULL;
382            pScrn->vtSema = TRUE;
383            (*pScreenPriv->funcs->SetMode) (pScrn, NULL);
384            if (pScreenPriv->savedColormap) {
385                (*pScreen->InstallColormap) (pScreenPriv->savedColormap);
386                pScreenPriv->savedColormap = NULL;
387            }
388            pScreenPriv->dgaColormap = NULL;
389            (*pScrn->EnableDisableFBAccess) (pScrn, TRUE);
390
391            FreeMarkedVisuals(pScreen);
392        }
393
394        pScreenPriv->grabMouse = FALSE;
395        pScreenPriv->grabKeyboard = FALSE;
396
397        return Success;
398    }
399
400    if (!pScrn->vtSema && !pScreenPriv->current)        /* Really switched away */
401        return BadAlloc;
402
403    if ((num > 0) && (num <= pScreenPriv->numModes))
404        pMode = &(pScreenPriv->modes[num - 1]);
405    else
406        return BadValue;
407
408    if (!(device = (DGADevicePtr) malloc(sizeof(DGADeviceRec))))
409        return BadAlloc;
410
411    if (!pScreenPriv->current) {
412        Bool oldVTSema = pScrn->vtSema;
413
414        pScrn->vtSema = FALSE;  /* kludge until we rewrite VT switching */
415        (*pScrn->EnableDisableFBAccess) (pScrn, FALSE);
416        pScrn->vtSema = oldVTSema;
417    }
418
419    if (!(*pScreenPriv->funcs->SetMode) (pScrn, pMode)) {
420        free(device);
421        return BadAlloc;
422    }
423
424    pScrn->currentMode = pMode->mode;
425
426    if (!pScreenPriv->current && !pScreenPriv->input) {
427        /* if it's multihead we need to warp the cursor off of
428           our screen so it doesn't get trapped  */
429    }
430
431    pScrn->vtSema = FALSE;
432
433    if (pScreenPriv->current) {
434        PixmapPtr oldPix = pScreenPriv->current->pPix;
435
436        if (oldPix) {
437            if (oldPix->drawable.id)
438                FreeResource(oldPix->drawable.id, RT_NONE);
439            else
440                (*pScreen->DestroyPixmap) (oldPix);
441        }
442        free(pScreenPriv->current);
443        pScreenPriv->current = NULL;
444    }
445
446    if (pMode->flags & DGA_PIXMAP_AVAILABLE) {
447        if ((pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pMode->depth, 0))) {
448            (*pScreen->ModifyPixmapHeader) (pPix,
449                                            pMode->pixmapWidth,
450                                            pMode->pixmapHeight, pMode->depth,
451                                            pMode->bitsPerPixel,
452                                            pMode->bytesPerScanline,
453                                            (void *) (pMode->address));
454        }
455    }
456
457    devRet->mode = device->mode = pMode;
458    devRet->pPix = device->pPix = pPix;
459    pScreenPriv->current = device;
460    pScreenPriv->pixmapMode = FALSE;
461    pScreenPriv->grabMouse = TRUE;
462    pScreenPriv->grabKeyboard = TRUE;
463
464    if (!mieq_installed) {
465        mieqSetHandler(ET_DGAEvent, DGAHandleEvent);
466        mieq_installed = TRUE;
467    }
468
469    return Success;
470}
471
472/*********** exported ones ***************/
473
474static void
475DGASetInputMode(int index, Bool keyboard, Bool mouse)
476{
477    ScreenPtr pScreen = screenInfo.screens[index];
478    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
479
480    if (pScreenPriv) {
481        pScreenPriv->grabMouse = mouse;
482        pScreenPriv->grabKeyboard = keyboard;
483
484        if (!mieq_installed) {
485            mieqSetHandler(ET_DGAEvent, DGAHandleEvent);
486            mieq_installed = TRUE;
487        }
488    }
489}
490
491static Bool
492DGAChangePixmapMode(int index, int *x, int *y, int mode)
493{
494    DGAScreenPtr pScreenPriv;
495    DGADevicePtr pDev;
496    DGAModePtr pMode;
497    PixmapPtr pPix;
498
499    if (!DGAScreenKeyRegistered)
500        return FALSE;
501
502    pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
503
504    if (!pScreenPriv || !pScreenPriv->current || !pScreenPriv->current->pPix)
505        return FALSE;
506
507    pDev = pScreenPriv->current;
508    pPix = pDev->pPix;
509    pMode = pDev->mode;
510
511    if (mode) {
512        int shift = 2;
513
514        if (*x > (pMode->pixmapWidth - pMode->viewportWidth))
515            *x = pMode->pixmapWidth - pMode->viewportWidth;
516        if (*y > (pMode->pixmapHeight - pMode->viewportHeight))
517            *y = pMode->pixmapHeight - pMode->viewportHeight;
518
519        switch (xf86Screens[index]->bitsPerPixel) {
520        case 16:
521            shift = 1;
522            break;
523        case 32:
524            shift = 0;
525            break;
526        default:
527            break;
528        }
529
530        if (BITMAP_SCANLINE_PAD == 64)
531            shift++;
532
533        *x = (*x >> shift) << shift;
534
535        pPix->drawable.x = *x;
536        pPix->drawable.y = *y;
537        pPix->drawable.width = pMode->viewportWidth;
538        pPix->drawable.height = pMode->viewportHeight;
539    }
540    else {
541        pPix->drawable.x = 0;
542        pPix->drawable.y = 0;
543        pPix->drawable.width = pMode->pixmapWidth;
544        pPix->drawable.height = pMode->pixmapHeight;
545    }
546    pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
547    pScreenPriv->pixmapMode = mode;
548
549    return TRUE;
550}
551
552Bool
553DGAScreenAvailable(ScreenPtr pScreen)
554{
555    if (!DGAScreenKeyRegistered)
556        return FALSE;
557
558    if (DGA_GET_SCREEN_PRIV(pScreen))
559        return TRUE;
560    return FALSE;
561}
562
563static Bool
564DGAAvailable(int index)
565{
566    ScreenPtr pScreen;
567
568    assert(index < MAXSCREENS);
569    pScreen = screenInfo.screens[index];
570    return DGAScreenAvailable(pScreen);
571}
572
573Bool
574DGAActive(int index)
575{
576    DGAScreenPtr pScreenPriv;
577
578    if (!DGAScreenKeyRegistered)
579        return FALSE;
580
581    pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
582
583    if (pScreenPriv && pScreenPriv->current)
584        return TRUE;
585
586    return FALSE;
587}
588
589/* Called by the event code in case the server is abruptly terminated */
590
591void
592DGAShutdown(void)
593{
594    ScrnInfoPtr pScrn;
595    int i;
596
597    if (!DGAScreenKeyRegistered)
598        return;
599
600    for (i = 0; i < screenInfo.numScreens; i++) {
601        pScrn = xf86Screens[i];
602
603        (void) (*pScrn->SetDGAMode) (pScrn, 0, NULL);
604    }
605}
606
607/* Called by the extension to initialize a mode */
608
609static int
610DGASetMode(int index, int num, XDGAModePtr mode, PixmapPtr *pPix)
611{
612    ScrnInfoPtr pScrn = xf86Screens[index];
613    DGADeviceRec device;
614    int ret;
615
616    /* We rely on the extension to check that DGA is available */
617
618    ret = (*pScrn->SetDGAMode) (pScrn, num, &device);
619    if ((ret == Success) && num) {
620        DGACopyModeInfo(device.mode, mode);
621        *pPix = device.pPix;
622    }
623
624    return ret;
625}
626
627/* Called from the extension to let the DDX know which events are requested */
628
629static void
630DGASelectInput(int index, ClientPtr client, long mask)
631{
632    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
633
634    /* We rely on the extension to check that DGA is available */
635    pScreenPriv->client = client;
636    pScreenPriv->input = mask;
637}
638
639static int
640DGAGetViewportStatus(int index)
641{
642    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
643
644    /* We rely on the extension to check that DGA is active */
645
646    if (!pScreenPriv->funcs->GetViewport)
647        return 0;
648
649    return (*pScreenPriv->funcs->GetViewport) (pScreenPriv->pScrn);
650}
651
652static int
653DGASetViewport(int index, int x, int y, int mode)
654{
655    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
656
657    if (pScreenPriv->funcs->SetViewport)
658        (*pScreenPriv->funcs->SetViewport) (pScreenPriv->pScrn, x, y, mode);
659    return Success;
660}
661
662static int
663BitsClear(CARD32 data)
664{
665    int bits = 0;
666    CARD32 mask;
667
668    for (mask = 1; mask; mask <<= 1) {
669        if (!(data & mask))
670            bits++;
671        else
672            break;
673    }
674
675    return bits;
676}
677
678static int
679DGACreateColormap(int index, ClientPtr client, int id, int mode, int alloc)
680{
681    ScreenPtr pScreen = screenInfo.screens[index];
682    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
683    FakedVisualList *fvlp;
684    VisualPtr pVisual;
685    DGAModePtr pMode;
686    ColormapPtr pmap;
687
688    if (!mode || (mode > pScreenPriv->numModes))
689        return BadValue;
690
691    if ((alloc != AllocNone) && (alloc != AllocAll))
692        return BadValue;
693
694    pMode = &(pScreenPriv->modes[mode - 1]);
695
696    if (!(pVisual = malloc(sizeof(VisualRec))))
697        return BadAlloc;
698
699    pVisual->vid = FakeClientID(0);
700    pVisual->class = pMode->visualClass;
701    pVisual->nplanes = pMode->depth;
702    pVisual->ColormapEntries = 1 << pMode->depth;
703    pVisual->bitsPerRGBValue = (pMode->depth + 2) / 3;
704
705    switch (pVisual->class) {
706    case PseudoColor:
707    case GrayScale:
708    case StaticGray:
709        pVisual->bitsPerRGBValue = 8;   /* not quite */
710        pVisual->redMask = 0;
711        pVisual->greenMask = 0;
712        pVisual->blueMask = 0;
713        pVisual->offsetRed = 0;
714        pVisual->offsetGreen = 0;
715        pVisual->offsetBlue = 0;
716        break;
717    case DirectColor:
718    case TrueColor:
719        pVisual->ColormapEntries = 1 << pVisual->bitsPerRGBValue;
720        /* fall through */
721    case StaticColor:
722        pVisual->redMask = pMode->red_mask;
723        pVisual->greenMask = pMode->green_mask;
724        pVisual->blueMask = pMode->blue_mask;
725        pVisual->offsetRed = BitsClear(pVisual->redMask);
726        pVisual->offsetGreen = BitsClear(pVisual->greenMask);
727        pVisual->offsetBlue = BitsClear(pVisual->blueMask);
728    }
729
730    if (!(fvlp = malloc(sizeof(FakedVisualList)))) {
731        free(pVisual);
732        return BadAlloc;
733    }
734
735    fvlp->free = FALSE;
736    fvlp->pVisual = pVisual;
737    fvlp->next = pScreenPriv->fakedVisuals;
738    pScreenPriv->fakedVisuals = fvlp;
739
740    LEGAL_NEW_RESOURCE(id, client);
741
742    return CreateColormap(id, pScreen, pVisual, &pmap, alloc, client->index);
743}
744
745/*  Called by the extension to install a colormap on DGA active screens */
746
747static void
748DGAInstallCmap(ColormapPtr cmap)
749{
750    ScreenPtr pScreen = cmap->pScreen;
751    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
752
753    /* We rely on the extension to check that DGA is active */
754
755    if (!pScreenPriv->dgaColormap)
756        pScreenPriv->savedColormap = GetInstalledmiColormap(pScreen);
757
758    pScreenPriv->dgaColormap = cmap;
759
760    (*pScreen->InstallColormap) (cmap);
761}
762
763static int
764DGASync(int index)
765{
766    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
767
768    /* We rely on the extension to check that DGA is active */
769
770    if (pScreenPriv->funcs->Sync)
771        (*pScreenPriv->funcs->Sync) (pScreenPriv->pScrn);
772
773    return Success;
774}
775
776static int
777DGAFillRect(int index, int x, int y, int w, int h, unsigned long color)
778{
779    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
780
781    /* We rely on the extension to check that DGA is active */
782
783    if (pScreenPriv->funcs->FillRect &&
784        (pScreenPriv->current->mode->flags & DGA_FILL_RECT)) {
785
786        (*pScreenPriv->funcs->FillRect) (pScreenPriv->pScrn, x, y, w, h, color);
787        return Success;
788    }
789    return BadMatch;
790}
791
792static int
793DGABlitRect(int index, int srcx, int srcy, int w, int h, int dstx, int dsty)
794{
795    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
796
797    /* We rely on the extension to check that DGA is active */
798
799    if (pScreenPriv->funcs->BlitRect &&
800        (pScreenPriv->current->mode->flags & DGA_BLIT_RECT)) {
801
802        (*pScreenPriv->funcs->BlitRect) (pScreenPriv->pScrn,
803                                         srcx, srcy, w, h, dstx, dsty);
804        return Success;
805    }
806    return BadMatch;
807}
808
809static int
810DGABlitTransRect(int index,
811                 int srcx, int srcy,
812                 int w, int h, int dstx, int dsty, unsigned long color)
813{
814    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
815
816    /* We rely on the extension to check that DGA is active */
817
818    if (pScreenPriv->funcs->BlitTransRect &&
819        (pScreenPriv->current->mode->flags & DGA_BLIT_RECT_TRANS)) {
820
821        (*pScreenPriv->funcs->BlitTransRect) (pScreenPriv->pScrn,
822                                              srcx, srcy, w, h, dstx, dsty,
823                                              color);
824        return Success;
825    }
826    return BadMatch;
827}
828
829static int
830DGAGetModes(int index)
831{
832    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
833
834    /* We rely on the extension to check that DGA is available */
835
836    return pScreenPriv->numModes;
837}
838
839static int
840DGAGetModeInfo(int index, XDGAModePtr mode, int num)
841{
842    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
843
844    /* We rely on the extension to check that DGA is available */
845
846    if ((num <= 0) || (num > pScreenPriv->numModes))
847        return BadValue;
848
849    DGACopyModeInfo(&(pScreenPriv->modes[num - 1]), mode);
850
851    return Success;
852}
853
854static void
855DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode)
856{
857    DisplayModePtr dmode = mode->mode;
858
859    xmode->num = mode->num;
860    xmode->name = dmode->name;
861    xmode->VSync_num = (int) (dmode->VRefresh * 1000.0);
862    xmode->VSync_den = 1000;
863    xmode->flags = mode->flags;
864    xmode->imageWidth = mode->imageWidth;
865    xmode->imageHeight = mode->imageHeight;
866    xmode->pixmapWidth = mode->pixmapWidth;
867    xmode->pixmapHeight = mode->pixmapHeight;
868    xmode->bytesPerScanline = mode->bytesPerScanline;
869    xmode->byteOrder = mode->byteOrder;
870    xmode->depth = mode->depth;
871    xmode->bitsPerPixel = mode->bitsPerPixel;
872    xmode->red_mask = mode->red_mask;
873    xmode->green_mask = mode->green_mask;
874    xmode->blue_mask = mode->blue_mask;
875    xmode->visualClass = mode->visualClass;
876    xmode->viewportWidth = mode->viewportWidth;
877    xmode->viewportHeight = mode->viewportHeight;
878    xmode->xViewportStep = mode->xViewportStep;
879    xmode->yViewportStep = mode->yViewportStep;
880    xmode->maxViewportX = mode->maxViewportX;
881    xmode->maxViewportY = mode->maxViewportY;
882    xmode->viewportFlags = mode->viewportFlags;
883    xmode->reserved1 = mode->reserved1;
884    xmode->reserved2 = mode->reserved2;
885    xmode->offset = mode->offset;
886
887    if (dmode->Flags & V_INTERLACE)
888        xmode->flags |= DGA_INTERLACED;
889    if (dmode->Flags & V_DBLSCAN)
890        xmode->flags |= DGA_DOUBLESCAN;
891}
892
893Bool
894DGAVTSwitch(void)
895{
896    ScreenPtr pScreen;
897    int i;
898
899    for (i = 0; i < screenInfo.numScreens; i++) {
900        pScreen = screenInfo.screens[i];
901
902        /* Alternatively, this could send events to DGA clients */
903
904        if (DGAScreenKeyRegistered) {
905            DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
906
907            if (pScreenPriv && pScreenPriv->current)
908                return FALSE;
909        }
910    }
911
912    return TRUE;
913}
914
915Bool
916DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down)
917{
918    DGAScreenPtr pScreenPriv;
919    DGAEvent event;
920
921    if (!DGAScreenKeyRegistered)        /* no DGA */
922        return FALSE;
923
924    if (key_code < 8 || key_code > 255)
925        return FALSE;
926
927    pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
928
929    if (!pScreenPriv || !pScreenPriv->grabKeyboard)     /* no direct mode */
930        return FALSE;
931
932    event = (DGAEvent) {
933        .header = ET_Internal,
934        .type = ET_DGAEvent,
935        .length = sizeof(event),
936        .time = GetTimeInMillis(),
937        .subtype = (is_down ? ET_KeyPress : ET_KeyRelease),
938        .detail = key_code,
939        .dx = 0,
940        .dy = 0
941    };
942    mieqEnqueue(dev, (InternalEvent *) &event);
943
944    return TRUE;
945}
946
947Bool
948DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy)
949{
950    DGAScreenPtr pScreenPriv;
951    DGAEvent event;
952
953    if (!DGAScreenKeyRegistered)        /* no DGA */
954        return FALSE;
955
956    pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
957
958    if (!pScreenPriv || !pScreenPriv->grabMouse)        /* no direct mode */
959        return FALSE;
960
961    event = (DGAEvent) {
962        .header = ET_Internal,
963        .type = ET_DGAEvent,
964        .length = sizeof(event),
965        .time = GetTimeInMillis(),
966        .subtype = ET_Motion,
967        .detail = 0,
968        .dx = dx,
969        .dy = dy
970    };
971    mieqEnqueue(dev, (InternalEvent *) &event);
972    return TRUE;
973}
974
975Bool
976DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down)
977{
978    DGAScreenPtr pScreenPriv;
979    DGAEvent event;
980
981    if (!DGAScreenKeyRegistered)        /* no DGA */
982        return FALSE;
983
984    pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
985
986    if (!pScreenPriv || !pScreenPriv->grabMouse)
987        return FALSE;
988
989    event = (DGAEvent) {
990        .header = ET_Internal,
991        .type = ET_DGAEvent,
992        .length = sizeof(event),
993        .time = GetTimeInMillis(),
994        .subtype = (is_down ? ET_ButtonPress : ET_ButtonRelease),
995        .detail = button,
996        .dx = 0,
997        .dy = 0
998    };
999    mieqEnqueue(dev, (InternalEvent *) &event);
1000
1001    return TRUE;
1002}
1003
1004/* We have the power to steal or modify events that are about to get queued */
1005
1006#define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
1007static Mask filters[] = {
1008    NoSuchEvent,                /* 0 */
1009    NoSuchEvent,                /* 1 */
1010    KeyPressMask,               /* KeyPress */
1011    KeyReleaseMask,             /* KeyRelease */
1012    ButtonPressMask,            /* ButtonPress */
1013    ButtonReleaseMask,          /* ButtonRelease */
1014    PointerMotionMask,          /* MotionNotify (initial state) */
1015};
1016
1017static void
1018DGAProcessKeyboardEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr keybd)
1019{
1020    KeyClassPtr keyc = keybd->key;
1021    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
1022    DeviceIntPtr pointer = GetMaster(keybd, POINTER_OR_FLOAT);
1023    DeviceEvent ev = {
1024        .header = ET_Internal,
1025        .length = sizeof(ev),
1026        .detail.key = event->detail,
1027        .type = event->subtype,
1028        .root_x = 0,
1029        .root_y = 0,
1030        .corestate = XkbStateFieldFromRec(&keyc->xkbInfo->state)
1031    };
1032    ev.corestate |= pointer->button->state;
1033
1034    UpdateDeviceState(keybd, &ev);
1035
1036    if (!IsMaster(keybd))
1037        return;
1038
1039    /*
1040     * Deliver the DGA event
1041     */
1042    if (pScreenPriv->client) {
1043        dgaEvent de = {
1044            .u.event.time = event->time,
1045            .u.event.dx = event->dx,
1046            .u.event.dy = event->dy,
1047            .u.event.screen = pScreen->myNum,
1048            .u.event.state = ev.corestate
1049        };
1050        de.u.u.type = DGAEventBase + GetCoreType(ev.type);
1051        de.u.u.detail = event->detail;
1052
1053        /* If the DGA client has selected input, then deliver based on the usual filter */
1054        TryClientEvents(pScreenPriv->client, keybd, (xEvent *) &de, 1,
1055                        filters[ev.type], pScreenPriv->input, 0);
1056    }
1057    else {
1058        /* If the keyboard is actively grabbed, deliver a grabbed core event */
1059        if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) {
1060            ev.detail.key = event->detail;
1061            ev.time = event->time;
1062            ev.root_x = event->dx;
1063            ev.root_y = event->dy;
1064            ev.corestate = event->state;
1065            ev.deviceid = keybd->id;
1066            DeliverGrabbedEvent((InternalEvent *) &ev, keybd, FALSE);
1067        }
1068    }
1069}
1070
1071static void
1072DGAProcessPointerEvent(ScreenPtr pScreen, DGAEvent * event, DeviceIntPtr mouse)
1073{
1074    ButtonClassPtr butc = mouse->button;
1075    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
1076    DeviceIntPtr master = GetMaster(mouse, MASTER_KEYBOARD);
1077    DeviceEvent ev = {
1078        .header = ET_Internal,
1079        .length = sizeof(ev),
1080        .detail.key = event->detail,
1081        .type = event->subtype,
1082        .corestate = butc ? butc->state : 0
1083    };
1084
1085    if (master && master->key)
1086        ev.corestate |= XkbStateFieldFromRec(&master->key->xkbInfo->state);
1087
1088    UpdateDeviceState(mouse, &ev);
1089
1090    if (!IsMaster(mouse))
1091        return;
1092
1093    /*
1094     * Deliver the DGA event
1095     */
1096    if (pScreenPriv->client) {
1097        int coreEquiv = GetCoreType(ev.type);
1098        dgaEvent de = {
1099            .u.event.time = event->time,
1100            .u.event.dx = event->dx,
1101            .u.event.dy = event->dy,
1102            .u.event.screen = pScreen->myNum,
1103            .u.event.state = ev.corestate
1104        };
1105        de.u.u.type = DGAEventBase + coreEquiv;
1106        de.u.u.detail = event->detail;
1107
1108        /* If the DGA client has selected input, then deliver based on the usual filter */
1109        TryClientEvents(pScreenPriv->client, mouse, (xEvent *) &de, 1,
1110                        filters[coreEquiv], pScreenPriv->input, 0);
1111    }
1112    else {
1113        /* If the pointer is actively grabbed, deliver a grabbed core event */
1114        if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) {
1115            ev.detail.button = event->detail;
1116            ev.time = event->time;
1117            ev.root_x = event->dx;
1118            ev.root_y = event->dy;
1119            ev.corestate = event->state;
1120            /* DGA is core only, so valuators.data doesn't actually matter.
1121             * Mask must be set for EventToCore to create motion events. */
1122            SetBit(ev.valuators.mask, 0);
1123            SetBit(ev.valuators.mask, 1);
1124            DeliverGrabbedEvent((InternalEvent *) &ev, mouse, FALSE);
1125        }
1126    }
1127}
1128
1129static Bool
1130DGAOpenFramebuffer(int index,
1131                   char **name,
1132                   unsigned char **mem, int *size, int *offset, int *flags)
1133{
1134    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
1135
1136    /* We rely on the extension to check that DGA is available */
1137
1138    return (*pScreenPriv->funcs->OpenFramebuffer) (pScreenPriv->pScrn,
1139                                                   name, mem, size, offset,
1140                                                   flags);
1141}
1142
1143static void
1144DGACloseFramebuffer(int index)
1145{
1146    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
1147
1148    /* We rely on the extension to check that DGA is available */
1149    if (pScreenPriv->funcs->CloseFramebuffer)
1150        (*pScreenPriv->funcs->CloseFramebuffer) (pScreenPriv->pScrn);
1151}
1152
1153/*  For DGA 1.0 backwards compatibility only */
1154
1155static int
1156DGAGetOldDGAMode(int index)
1157{
1158    DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(screenInfo.screens[index]);
1159    ScrnInfoPtr pScrn = pScreenPriv->pScrn;
1160    DGAModePtr mode;
1161    int i, w, h, p;
1162
1163    /* We rely on the extension to check that DGA is available */
1164
1165    w = pScrn->currentMode->HDisplay;
1166    h = pScrn->currentMode->VDisplay;
1167    p = pad_to_int32(pScrn->displayWidth * bits_to_bytes(pScrn->bitsPerPixel));
1168
1169    for (i = 0; i < pScreenPriv->numModes; i++) {
1170        mode = &(pScreenPriv->modes[i]);
1171
1172        if ((mode->viewportWidth == w) && (mode->viewportHeight == h) &&
1173            (mode->bytesPerScanline == p) &&
1174            (mode->bitsPerPixel == pScrn->bitsPerPixel) &&
1175            (mode->depth == pScrn->depth)) {
1176
1177            return mode->num;
1178        }
1179    }
1180
1181    return 0;
1182}
1183
1184static void
1185DGAHandleEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
1186{
1187    DGAEvent *event = &ev->dga_event;
1188    ScreenPtr pScreen = screenInfo.screens[screen_num];
1189    DGAScreenPtr pScreenPriv;
1190
1191    /* no DGA */
1192    if (!DGAScreenKeyRegistered || noXFree86DGAExtension)
1193	return;
1194    pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen);
1195
1196    /* DGA not initialized on this screen */
1197    if (!pScreenPriv)
1198        return;
1199
1200    switch (event->subtype) {
1201    case KeyPress:
1202    case KeyRelease:
1203        DGAProcessKeyboardEvent(pScreen, event, device);
1204        break;
1205    case MotionNotify:
1206    case ButtonPress:
1207    case ButtonRelease:
1208        DGAProcessPointerEvent(pScreen, event, device);
1209        break;
1210    default:
1211        break;
1212    }
1213}
1214
1215static void XDGAResetProc(ExtensionEntry * extEntry);
1216
1217static void DGAClientStateChange(CallbackListPtr *, void *, void *);
1218
1219static DevPrivateKeyRec DGAScreenPrivateKeyRec;
1220
1221#define DGAScreenPrivateKey (&DGAScreenPrivateKeyRec)
1222#define DGAScreenPrivateKeyRegistered (DGAScreenPrivateKeyRec.initialized)
1223static DevPrivateKeyRec DGAClientPrivateKeyRec;
1224
1225#define DGAClientPrivateKey (&DGAClientPrivateKeyRec)
1226static int DGACallbackRefCount = 0;
1227
1228/* This holds the client's version information */
1229typedef struct {
1230    int major;
1231    int minor;
1232} DGAPrivRec, *DGAPrivPtr;
1233
1234#define DGA_GETCLIENT(idx) ((ClientPtr) \
1235    dixLookupPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey))
1236#define DGA_SETCLIENT(idx,p) \
1237    dixSetPrivate(&screenInfo.screens[idx]->devPrivates, DGAScreenPrivateKey, p)
1238
1239#define DGA_GETPRIV(c) ((DGAPrivPtr) \
1240    dixLookupPrivate(&(c)->devPrivates, DGAClientPrivateKey))
1241#define DGA_SETPRIV(c,p) \
1242    dixSetPrivate(&(c)->devPrivates, DGAClientPrivateKey, p)
1243
1244static void
1245XDGAResetProc(ExtensionEntry * extEntry)
1246{
1247    DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1248    DGACallbackRefCount = 0;
1249}
1250
1251static int
1252ProcXDGAQueryVersion(ClientPtr client)
1253{
1254    xXDGAQueryVersionReply rep;
1255
1256    REQUEST_SIZE_MATCH(xXDGAQueryVersionReq);
1257    rep.type = X_Reply;
1258    rep.length = 0;
1259    rep.sequenceNumber = client->sequence;
1260    rep.majorVersion = SERVER_XDGA_MAJOR_VERSION;
1261    rep.minorVersion = SERVER_XDGA_MINOR_VERSION;
1262
1263    WriteToClient(client, sizeof(xXDGAQueryVersionReply), (char *) &rep);
1264    return Success;
1265}
1266
1267static int
1268ProcXDGAOpenFramebuffer(ClientPtr client)
1269{
1270    REQUEST(xXDGAOpenFramebufferReq);
1271    xXDGAOpenFramebufferReply rep;
1272    char *deviceName;
1273    int nameSize;
1274
1275    if (stuff->screen >= screenInfo.numScreens)
1276        return BadValue;
1277
1278    if (!DGAAvailable(stuff->screen))
1279        return DGAErrorBase + XF86DGANoDirectVideoMode;
1280
1281    REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq);
1282    rep.type = X_Reply;
1283    rep.length = 0;
1284    rep.sequenceNumber = client->sequence;
1285
1286    if (!DGAOpenFramebuffer(stuff->screen, &deviceName,
1287                            (unsigned char **) (&rep.mem1),
1288                            (int *) &rep.size, (int *) &rep.offset,
1289                            (int *) &rep.extra)) {
1290        return BadAlloc;
1291    }
1292
1293    nameSize = deviceName ? (strlen(deviceName) + 1) : 0;
1294    rep.length = bytes_to_int32(nameSize);
1295
1296    WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *) &rep);
1297    if (rep.length)
1298        WriteToClient(client, nameSize, deviceName);
1299
1300    return Success;
1301}
1302
1303static int
1304ProcXDGACloseFramebuffer(ClientPtr client)
1305{
1306    REQUEST(xXDGACloseFramebufferReq);
1307
1308    if (stuff->screen >= screenInfo.numScreens)
1309        return BadValue;
1310
1311    if (!DGAAvailable(stuff->screen))
1312        return DGAErrorBase + XF86DGANoDirectVideoMode;
1313
1314    REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq);
1315
1316    DGACloseFramebuffer(stuff->screen);
1317
1318    return Success;
1319}
1320
1321static int
1322ProcXDGAQueryModes(ClientPtr client)
1323{
1324    int i, num, size;
1325
1326    REQUEST(xXDGAQueryModesReq);
1327    xXDGAQueryModesReply rep;
1328    xXDGAModeInfo info;
1329    XDGAModePtr mode;
1330
1331    if (stuff->screen >= screenInfo.numScreens)
1332        return BadValue;
1333
1334    REQUEST_SIZE_MATCH(xXDGAQueryModesReq);
1335    rep.type = X_Reply;
1336    rep.length = 0;
1337    rep.number = 0;
1338    rep.sequenceNumber = client->sequence;
1339
1340    if (!DGAAvailable(stuff->screen)) {
1341        rep.number = 0;
1342        rep.length = 0;
1343        WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1344        return Success;
1345    }
1346
1347    if (!(num = DGAGetModes(stuff->screen))) {
1348        WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1349        return Success;
1350    }
1351
1352    if (!(mode = xallocarray(num, sizeof(XDGAModeRec))))
1353        return BadAlloc;
1354
1355    for (i = 0; i < num; i++)
1356        DGAGetModeInfo(stuff->screen, mode + i, i + 1);
1357
1358    size = num * sz_xXDGAModeInfo;
1359    for (i = 0; i < num; i++)
1360        size += pad_to_int32(strlen(mode[i].name) + 1); /* plus NULL */
1361
1362    rep.number = num;
1363    rep.length = bytes_to_int32(size);
1364
1365    WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1366
1367    for (i = 0; i < num; i++) {
1368        size = strlen(mode[i].name) + 1;
1369
1370        info.byte_order = mode[i].byteOrder;
1371        info.depth = mode[i].depth;
1372        info.num = mode[i].num;
1373        info.bpp = mode[i].bitsPerPixel;
1374        info.name_size = (size + 3) & ~3L;
1375        info.vsync_num = mode[i].VSync_num;
1376        info.vsync_den = mode[i].VSync_den;
1377        info.flags = mode[i].flags;
1378        info.image_width = mode[i].imageWidth;
1379        info.image_height = mode[i].imageHeight;
1380        info.pixmap_width = mode[i].pixmapWidth;
1381        info.pixmap_height = mode[i].pixmapHeight;
1382        info.bytes_per_scanline = mode[i].bytesPerScanline;
1383        info.red_mask = mode[i].red_mask;
1384        info.green_mask = mode[i].green_mask;
1385        info.blue_mask = mode[i].blue_mask;
1386        info.visual_class = mode[i].visualClass;
1387        info.viewport_width = mode[i].viewportWidth;
1388        info.viewport_height = mode[i].viewportHeight;
1389        info.viewport_xstep = mode[i].xViewportStep;
1390        info.viewport_ystep = mode[i].yViewportStep;
1391        info.viewport_xmax = mode[i].maxViewportX;
1392        info.viewport_ymax = mode[i].maxViewportY;
1393        info.viewport_flags = mode[i].viewportFlags;
1394        info.reserved1 = mode[i].reserved1;
1395        info.reserved2 = mode[i].reserved2;
1396
1397        WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info));
1398        WriteToClient(client, size, mode[i].name);
1399    }
1400
1401    free(mode);
1402
1403    return Success;
1404}
1405
1406static void
1407DGAClientStateChange(CallbackListPtr *pcbl, void *nulldata, void *calldata)
1408{
1409    NewClientInfoRec *pci = (NewClientInfoRec *) calldata;
1410    ClientPtr client = NULL;
1411    int i;
1412
1413    for (i = 0; i < screenInfo.numScreens; i++) {
1414        if (DGA_GETCLIENT(i) == pci->client) {
1415            client = pci->client;
1416            break;
1417        }
1418    }
1419
1420    if (client &&
1421        ((client->clientState == ClientStateGone) ||
1422         (client->clientState == ClientStateRetained))) {
1423        XDGAModeRec mode;
1424        PixmapPtr pPix;
1425
1426        DGA_SETCLIENT(i, NULL);
1427        DGASelectInput(i, NULL, 0);
1428        DGASetMode(i, 0, &mode, &pPix);
1429
1430        if (--DGACallbackRefCount == 0)
1431            DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1432    }
1433}
1434
1435static int
1436ProcXDGASetMode(ClientPtr client)
1437{
1438    REQUEST(xXDGASetModeReq);
1439    xXDGASetModeReply rep;
1440    XDGAModeRec mode;
1441    xXDGAModeInfo info;
1442    PixmapPtr pPix;
1443    ClientPtr owner;
1444    int size;
1445
1446    if (stuff->screen >= screenInfo.numScreens)
1447        return BadValue;
1448    owner = DGA_GETCLIENT(stuff->screen);
1449
1450    REQUEST_SIZE_MATCH(xXDGASetModeReq);
1451    rep.type = X_Reply;
1452    rep.length = 0;
1453    rep.offset = 0;
1454    rep.flags = 0;
1455    rep.sequenceNumber = client->sequence;
1456
1457    if (!DGAAvailable(stuff->screen))
1458        return DGAErrorBase + XF86DGANoDirectVideoMode;
1459
1460    if (owner && owner != client)
1461        return DGAErrorBase + XF86DGANoDirectVideoMode;
1462
1463    if (!stuff->mode) {
1464        if (owner) {
1465            if (--DGACallbackRefCount == 0)
1466                DeleteCallback(&ClientStateCallback, DGAClientStateChange,
1467                               NULL);
1468        }
1469        DGA_SETCLIENT(stuff->screen, NULL);
1470        DGASelectInput(stuff->screen, NULL, 0);
1471        DGASetMode(stuff->screen, 0, &mode, &pPix);
1472        WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep);
1473        return Success;
1474    }
1475
1476    if (Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix))
1477        return BadValue;
1478
1479    if (!owner) {
1480        if (DGACallbackRefCount++ == 0)
1481            AddCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1482    }
1483
1484    DGA_SETCLIENT(stuff->screen, client);
1485
1486    if (pPix) {
1487        if (AddResource(stuff->pid, RT_PIXMAP, (void *) (pPix))) {
1488            pPix->drawable.id = (int) stuff->pid;
1489            rep.flags = DGA_PIXMAP_AVAILABLE;
1490        }
1491    }
1492
1493    size = strlen(mode.name) + 1;
1494
1495    info.byte_order = mode.byteOrder;
1496    info.depth = mode.depth;
1497    info.num = mode.num;
1498    info.bpp = mode.bitsPerPixel;
1499    info.name_size = (size + 3) & ~3L;
1500    info.vsync_num = mode.VSync_num;
1501    info.vsync_den = mode.VSync_den;
1502    info.flags = mode.flags;
1503    info.image_width = mode.imageWidth;
1504    info.image_height = mode.imageHeight;
1505    info.pixmap_width = mode.pixmapWidth;
1506    info.pixmap_height = mode.pixmapHeight;
1507    info.bytes_per_scanline = mode.bytesPerScanline;
1508    info.red_mask = mode.red_mask;
1509    info.green_mask = mode.green_mask;
1510    info.blue_mask = mode.blue_mask;
1511    info.visual_class = mode.visualClass;
1512    info.viewport_width = mode.viewportWidth;
1513    info.viewport_height = mode.viewportHeight;
1514    info.viewport_xstep = mode.xViewportStep;
1515    info.viewport_ystep = mode.yViewportStep;
1516    info.viewport_xmax = mode.maxViewportX;
1517    info.viewport_ymax = mode.maxViewportY;
1518    info.viewport_flags = mode.viewportFlags;
1519    info.reserved1 = mode.reserved1;
1520    info.reserved2 = mode.reserved2;
1521
1522    rep.length = bytes_to_int32(sz_xXDGAModeInfo + info.name_size);
1523
1524    WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep);
1525    WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info));
1526    WriteToClient(client, size, mode.name);
1527
1528    return Success;
1529}
1530
1531static int
1532ProcXDGASetViewport(ClientPtr client)
1533{
1534    REQUEST(xXDGASetViewportReq);
1535
1536    if (stuff->screen >= screenInfo.numScreens)
1537        return BadValue;
1538
1539    if (DGA_GETCLIENT(stuff->screen) != client)
1540        return DGAErrorBase + XF86DGADirectNotActivated;
1541
1542    REQUEST_SIZE_MATCH(xXDGASetViewportReq);
1543
1544    DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags);
1545
1546    return Success;
1547}
1548
1549static int
1550ProcXDGAInstallColormap(ClientPtr client)
1551{
1552    ColormapPtr cmap;
1553    int rc;
1554
1555    REQUEST(xXDGAInstallColormapReq);
1556
1557    if (stuff->screen >= screenInfo.numScreens)
1558        return BadValue;
1559
1560    if (DGA_GETCLIENT(stuff->screen) != client)
1561        return DGAErrorBase + XF86DGADirectNotActivated;
1562
1563    REQUEST_SIZE_MATCH(xXDGAInstallColormapReq);
1564
1565    rc = dixLookupResourceByType((void **) &cmap, stuff->cmap, RT_COLORMAP,
1566                                 client, DixInstallAccess);
1567    if (rc != Success)
1568        return rc;
1569    DGAInstallCmap(cmap);
1570    return Success;
1571}
1572
1573static int
1574ProcXDGASelectInput(ClientPtr client)
1575{
1576    REQUEST(xXDGASelectInputReq);
1577
1578    if (stuff->screen >= screenInfo.numScreens)
1579        return BadValue;
1580
1581    if (DGA_GETCLIENT(stuff->screen) != client)
1582        return DGAErrorBase + XF86DGADirectNotActivated;
1583
1584    REQUEST_SIZE_MATCH(xXDGASelectInputReq);
1585
1586    if (DGA_GETCLIENT(stuff->screen) == client)
1587        DGASelectInput(stuff->screen, client, stuff->mask);
1588
1589    return Success;
1590}
1591
1592static int
1593ProcXDGAFillRectangle(ClientPtr client)
1594{
1595    REQUEST(xXDGAFillRectangleReq);
1596
1597    if (stuff->screen >= screenInfo.numScreens)
1598        return BadValue;
1599
1600    if (DGA_GETCLIENT(stuff->screen) != client)
1601        return DGAErrorBase + XF86DGADirectNotActivated;
1602
1603    REQUEST_SIZE_MATCH(xXDGAFillRectangleReq);
1604
1605    if (Success != DGAFillRect(stuff->screen, stuff->x, stuff->y,
1606                               stuff->width, stuff->height, stuff->color))
1607        return BadMatch;
1608
1609    return Success;
1610}
1611
1612static int
1613ProcXDGACopyArea(ClientPtr client)
1614{
1615    REQUEST(xXDGACopyAreaReq);
1616
1617    if (stuff->screen >= screenInfo.numScreens)
1618        return BadValue;
1619
1620    if (DGA_GETCLIENT(stuff->screen) != client)
1621        return DGAErrorBase + XF86DGADirectNotActivated;
1622
1623    REQUEST_SIZE_MATCH(xXDGACopyAreaReq);
1624
1625    if (Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy,
1626                               stuff->width, stuff->height, stuff->dstx,
1627                               stuff->dsty))
1628        return BadMatch;
1629
1630    return Success;
1631}
1632
1633static int
1634ProcXDGACopyTransparentArea(ClientPtr client)
1635{
1636    REQUEST(xXDGACopyTransparentAreaReq);
1637
1638    if (stuff->screen >= screenInfo.numScreens)
1639        return BadValue;
1640
1641    if (DGA_GETCLIENT(stuff->screen) != client)
1642        return DGAErrorBase + XF86DGADirectNotActivated;
1643
1644    REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq);
1645
1646    if (Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy,
1647                                    stuff->width, stuff->height, stuff->dstx,
1648                                    stuff->dsty, stuff->key))
1649        return BadMatch;
1650
1651    return Success;
1652}
1653
1654static int
1655ProcXDGAGetViewportStatus(ClientPtr client)
1656{
1657    REQUEST(xXDGAGetViewportStatusReq);
1658    xXDGAGetViewportStatusReply rep;
1659
1660    if (stuff->screen >= screenInfo.numScreens)
1661        return BadValue;
1662
1663    if (DGA_GETCLIENT(stuff->screen) != client)
1664        return DGAErrorBase + XF86DGADirectNotActivated;
1665
1666    REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq);
1667    rep.type = X_Reply;
1668    rep.length = 0;
1669    rep.sequenceNumber = client->sequence;
1670
1671    rep.status = DGAGetViewportStatus(stuff->screen);
1672
1673    WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *) &rep);
1674    return Success;
1675}
1676
1677static int
1678ProcXDGASync(ClientPtr client)
1679{
1680    REQUEST(xXDGASyncReq);
1681    xXDGASyncReply rep;
1682
1683    if (stuff->screen >= screenInfo.numScreens)
1684        return BadValue;
1685
1686    if (DGA_GETCLIENT(stuff->screen) != client)
1687        return DGAErrorBase + XF86DGADirectNotActivated;
1688
1689    REQUEST_SIZE_MATCH(xXDGASyncReq);
1690    rep.type = X_Reply;
1691    rep.length = 0;
1692    rep.sequenceNumber = client->sequence;
1693
1694    DGASync(stuff->screen);
1695
1696    WriteToClient(client, sizeof(xXDGASyncReply), (char *) &rep);
1697    return Success;
1698}
1699
1700static int
1701ProcXDGASetClientVersion(ClientPtr client)
1702{
1703    REQUEST(xXDGASetClientVersionReq);
1704
1705    DGAPrivPtr pPriv;
1706
1707    REQUEST_SIZE_MATCH(xXDGASetClientVersionReq);
1708    if ((pPriv = DGA_GETPRIV(client)) == NULL) {
1709        pPriv = malloc(sizeof(DGAPrivRec));
1710        /* XXX Need to look into freeing this */
1711        if (!pPriv)
1712            return BadAlloc;
1713        DGA_SETPRIV(client, pPriv);
1714    }
1715    pPriv->major = stuff->major;
1716    pPriv->minor = stuff->minor;
1717
1718    return Success;
1719}
1720
1721static int
1722ProcXDGAChangePixmapMode(ClientPtr client)
1723{
1724    REQUEST(xXDGAChangePixmapModeReq);
1725    xXDGAChangePixmapModeReply rep;
1726    int x, y;
1727
1728    if (stuff->screen >= screenInfo.numScreens)
1729        return BadValue;
1730
1731    if (DGA_GETCLIENT(stuff->screen) != client)
1732        return DGAErrorBase + XF86DGADirectNotActivated;
1733
1734    REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq);
1735    rep.type = X_Reply;
1736    rep.length = 0;
1737    rep.sequenceNumber = client->sequence;
1738
1739    x = stuff->x;
1740    y = stuff->y;
1741
1742    if (!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags))
1743        return BadMatch;
1744
1745    rep.x = x;
1746    rep.y = y;
1747    WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *) &rep);
1748
1749    return Success;
1750}
1751
1752static int
1753ProcXDGACreateColormap(ClientPtr client)
1754{
1755    REQUEST(xXDGACreateColormapReq);
1756    int result;
1757
1758    if (stuff->screen >= screenInfo.numScreens)
1759        return BadValue;
1760
1761    if (DGA_GETCLIENT(stuff->screen) != client)
1762        return DGAErrorBase + XF86DGADirectNotActivated;
1763
1764    REQUEST_SIZE_MATCH(xXDGACreateColormapReq);
1765
1766    if (!stuff->mode)
1767        return BadValue;
1768
1769    result = DGACreateColormap(stuff->screen, client, stuff->id,
1770                               stuff->mode, stuff->alloc);
1771    if (result != Success)
1772        return result;
1773
1774    return Success;
1775}
1776
1777/*
1778 *
1779 * Support for the old DGA protocol, used to live in xf86dga.c
1780 *
1781 */
1782
1783#ifdef DGA_PROTOCOL_OLD_SUPPORT
1784
1785static int
1786ProcXF86DGAGetVideoLL(ClientPtr client)
1787{
1788    REQUEST(xXF86DGAGetVideoLLReq);
1789    xXF86DGAGetVideoLLReply rep;
1790    XDGAModeRec mode;
1791    int num, offset, flags;
1792    char *name;
1793
1794    if (stuff->screen >= screenInfo.numScreens)
1795        return BadValue;
1796
1797    REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq);
1798    rep.type = X_Reply;
1799    rep.length = 0;
1800    rep.sequenceNumber = client->sequence;
1801
1802    if (!DGAAvailable(stuff->screen))
1803        return DGAErrorBase + XF86DGANoDirectVideoMode;
1804
1805    if (!(num = DGAGetOldDGAMode(stuff->screen)))
1806        return DGAErrorBase + XF86DGANoDirectVideoMode;
1807
1808    /* get the parameters for the mode that best matches */
1809    DGAGetModeInfo(stuff->screen, &mode, num);
1810
1811    if (!DGAOpenFramebuffer(stuff->screen, &name,
1812                            (unsigned char **) (&rep.offset),
1813                            (int *) (&rep.bank_size), &offset, &flags))
1814        return BadAlloc;
1815
1816    rep.offset += mode.offset;
1817    rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3);
1818    rep.ram_size = rep.bank_size >> 10;
1819
1820    WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *) &rep);
1821    return Success;
1822}
1823
1824static int
1825ProcXF86DGADirectVideo(ClientPtr client)
1826{
1827    int num;
1828    PixmapPtr pix;
1829    XDGAModeRec mode;
1830    ClientPtr owner;
1831
1832    REQUEST(xXF86DGADirectVideoReq);
1833
1834    if (stuff->screen >= screenInfo.numScreens)
1835        return BadValue;
1836    REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq);
1837
1838    if (!DGAAvailable(stuff->screen))
1839        return DGAErrorBase + XF86DGANoDirectVideoMode;
1840
1841    owner = DGA_GETCLIENT(stuff->screen);
1842
1843    if (owner && owner != client)
1844        return DGAErrorBase + XF86DGANoDirectVideoMode;
1845
1846    if (stuff->enable & XF86DGADirectGraphics) {
1847        if (!(num = DGAGetOldDGAMode(stuff->screen)))
1848            return DGAErrorBase + XF86DGANoDirectVideoMode;
1849    }
1850    else
1851        num = 0;
1852
1853    if (Success != DGASetMode(stuff->screen, num, &mode, &pix))
1854        return DGAErrorBase + XF86DGAScreenNotActive;
1855
1856    DGASetInputMode(stuff->screen,
1857                    (stuff->enable & XF86DGADirectKeyb) != 0,
1858                    (stuff->enable & XF86DGADirectMouse) != 0);
1859
1860    /* We need to track the client and attach the teardown callback */
1861    if (stuff->enable &
1862        (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) {
1863        if (!owner) {
1864            if (DGACallbackRefCount++ == 0)
1865                AddCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1866        }
1867
1868        DGA_SETCLIENT(stuff->screen, client);
1869    }
1870    else {
1871        if (owner) {
1872            if (--DGACallbackRefCount == 0)
1873                DeleteCallback(&ClientStateCallback, DGAClientStateChange,
1874                               NULL);
1875        }
1876
1877        DGA_SETCLIENT(stuff->screen, NULL);
1878    }
1879
1880    return Success;
1881}
1882
1883static int
1884ProcXF86DGAGetViewPortSize(ClientPtr client)
1885{
1886    int num;
1887    XDGAModeRec mode;
1888
1889    REQUEST(xXF86DGAGetViewPortSizeReq);
1890    xXF86DGAGetViewPortSizeReply rep;
1891
1892    if (stuff->screen >= screenInfo.numScreens)
1893        return BadValue;
1894
1895    REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq);
1896    rep.type = X_Reply;
1897    rep.length = 0;
1898    rep.sequenceNumber = client->sequence;
1899
1900    if (!DGAAvailable(stuff->screen))
1901        return DGAErrorBase + XF86DGANoDirectVideoMode;
1902
1903    if (!(num = DGAGetOldDGAMode(stuff->screen)))
1904        return DGAErrorBase + XF86DGANoDirectVideoMode;
1905
1906    DGAGetModeInfo(stuff->screen, &mode, num);
1907
1908    rep.width = mode.viewportWidth;
1909    rep.height = mode.viewportHeight;
1910
1911    WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *) &rep);
1912    return Success;
1913}
1914
1915static int
1916ProcXF86DGASetViewPort(ClientPtr client)
1917{
1918    REQUEST(xXF86DGASetViewPortReq);
1919
1920    if (stuff->screen >= screenInfo.numScreens)
1921        return BadValue;
1922
1923    if (DGA_GETCLIENT(stuff->screen) != client)
1924        return DGAErrorBase + XF86DGADirectNotActivated;
1925
1926    REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq);
1927
1928    if (!DGAAvailable(stuff->screen))
1929        return DGAErrorBase + XF86DGANoDirectVideoMode;
1930
1931    if (!DGAActive(stuff->screen))
1932        return DGAErrorBase + XF86DGADirectNotActivated;
1933
1934    if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE)
1935        != Success)
1936        return DGAErrorBase + XF86DGADirectNotActivated;
1937
1938    return Success;
1939}
1940
1941static int
1942ProcXF86DGAGetVidPage(ClientPtr client)
1943{
1944    REQUEST(xXF86DGAGetVidPageReq);
1945    xXF86DGAGetVidPageReply rep;
1946
1947    if (stuff->screen >= screenInfo.numScreens)
1948        return BadValue;
1949
1950    REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq);
1951    rep.type = X_Reply;
1952    rep.length = 0;
1953    rep.sequenceNumber = client->sequence;
1954    rep.vpage = 0;              /* silently fail */
1955
1956    WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *) &rep);
1957    return Success;
1958}
1959
1960static int
1961ProcXF86DGASetVidPage(ClientPtr client)
1962{
1963    REQUEST(xXF86DGASetVidPageReq);
1964
1965    if (stuff->screen >= screenInfo.numScreens)
1966        return BadValue;
1967
1968    REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq);
1969
1970    /* silently fail */
1971
1972    return Success;
1973}
1974
1975static int
1976ProcXF86DGAInstallColormap(ClientPtr client)
1977{
1978    ColormapPtr pcmp;
1979    int rc;
1980
1981    REQUEST(xXF86DGAInstallColormapReq);
1982
1983    if (stuff->screen >= screenInfo.numScreens)
1984        return BadValue;
1985
1986    if (DGA_GETCLIENT(stuff->screen) != client)
1987        return DGAErrorBase + XF86DGADirectNotActivated;
1988
1989    REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq);
1990
1991    if (!DGAActive(stuff->screen))
1992        return DGAErrorBase + XF86DGADirectNotActivated;
1993
1994    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
1995                                 client, DixInstallAccess);
1996    if (rc == Success) {
1997        DGAInstallCmap(pcmp);
1998        return Success;
1999    }
2000    else {
2001        return rc;
2002    }
2003}
2004
2005static int
2006ProcXF86DGAQueryDirectVideo(ClientPtr client)
2007{
2008    REQUEST(xXF86DGAQueryDirectVideoReq);
2009    xXF86DGAQueryDirectVideoReply rep;
2010
2011    if (stuff->screen >= screenInfo.numScreens)
2012        return BadValue;
2013
2014    REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq);
2015    rep.type = X_Reply;
2016    rep.length = 0;
2017    rep.sequenceNumber = client->sequence;
2018    rep.flags = 0;
2019
2020    if (DGAAvailable(stuff->screen))
2021        rep.flags = XF86DGADirectPresent;
2022
2023    WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *) &rep);
2024    return Success;
2025}
2026
2027static int
2028ProcXF86DGAViewPortChanged(ClientPtr client)
2029{
2030    REQUEST(xXF86DGAViewPortChangedReq);
2031    xXF86DGAViewPortChangedReply rep;
2032
2033    if (stuff->screen >= screenInfo.numScreens)
2034        return BadValue;
2035
2036    if (DGA_GETCLIENT(stuff->screen) != client)
2037        return DGAErrorBase + XF86DGADirectNotActivated;
2038
2039    REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq);
2040
2041    if (!DGAActive(stuff->screen))
2042        return DGAErrorBase + XF86DGADirectNotActivated;
2043
2044    rep.type = X_Reply;
2045    rep.length = 0;
2046    rep.sequenceNumber = client->sequence;
2047    rep.result = 1;
2048
2049    WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *) &rep);
2050    return Success;
2051}
2052
2053#endif                          /* DGA_PROTOCOL_OLD_SUPPORT */
2054
2055static int
2056SProcXDGADispatch(ClientPtr client)
2057{
2058    return DGAErrorBase + XF86DGAClientNotLocal;
2059}
2060
2061#if 0
2062#define DGA_REQ_DEBUG
2063#endif
2064
2065#ifdef DGA_REQ_DEBUG
2066static char *dgaMinor[] = {
2067    "QueryVersion",
2068    "GetVideoLL",
2069    "DirectVideo",
2070    "GetViewPortSize",
2071    "SetViewPort",
2072    "GetVidPage",
2073    "SetVidPage",
2074    "InstallColormap",
2075    "QueryDirectVideo",
2076    "ViewPortChanged",
2077    "10",
2078    "11",
2079    "QueryModes",
2080    "SetMode",
2081    "SetViewport",
2082    "InstallColormap",
2083    "SelectInput",
2084    "FillRectangle",
2085    "CopyArea",
2086    "CopyTransparentArea",
2087    "GetViewportStatus",
2088    "Sync",
2089    "OpenFramebuffer",
2090    "CloseFramebuffer",
2091    "SetClientVersion",
2092    "ChangePixmapMode",
2093    "CreateColormap",
2094};
2095#endif
2096
2097static int
2098ProcXDGADispatch(ClientPtr client)
2099{
2100    REQUEST(xReq);
2101
2102    if (!client->local)
2103        return DGAErrorBase + XF86DGAClientNotLocal;
2104
2105#ifdef DGA_REQ_DEBUG
2106    if (stuff->data <= X_XDGACreateColormap)
2107        fprintf(stderr, "    DGA %s\n", dgaMinor[stuff->data]);
2108#endif
2109
2110    switch (stuff->data) {
2111        /*
2112         * DGA2 Protocol
2113         */
2114    case X_XDGAQueryVersion:
2115        return ProcXDGAQueryVersion(client);
2116    case X_XDGAQueryModes:
2117        return ProcXDGAQueryModes(client);
2118    case X_XDGASetMode:
2119        return ProcXDGASetMode(client);
2120    case X_XDGAOpenFramebuffer:
2121        return ProcXDGAOpenFramebuffer(client);
2122    case X_XDGACloseFramebuffer:
2123        return ProcXDGACloseFramebuffer(client);
2124    case X_XDGASetViewport:
2125        return ProcXDGASetViewport(client);
2126    case X_XDGAInstallColormap:
2127        return ProcXDGAInstallColormap(client);
2128    case X_XDGASelectInput:
2129        return ProcXDGASelectInput(client);
2130    case X_XDGAFillRectangle:
2131        return ProcXDGAFillRectangle(client);
2132    case X_XDGACopyArea:
2133        return ProcXDGACopyArea(client);
2134    case X_XDGACopyTransparentArea:
2135        return ProcXDGACopyTransparentArea(client);
2136    case X_XDGAGetViewportStatus:
2137        return ProcXDGAGetViewportStatus(client);
2138    case X_XDGASync:
2139        return ProcXDGASync(client);
2140    case X_XDGASetClientVersion:
2141        return ProcXDGASetClientVersion(client);
2142    case X_XDGAChangePixmapMode:
2143        return ProcXDGAChangePixmapMode(client);
2144    case X_XDGACreateColormap:
2145        return ProcXDGACreateColormap(client);
2146        /*
2147         * Old DGA Protocol
2148         */
2149#ifdef DGA_PROTOCOL_OLD_SUPPORT
2150    case X_XF86DGAGetVideoLL:
2151        return ProcXF86DGAGetVideoLL(client);
2152    case X_XF86DGADirectVideo:
2153        return ProcXF86DGADirectVideo(client);
2154    case X_XF86DGAGetViewPortSize:
2155        return ProcXF86DGAGetViewPortSize(client);
2156    case X_XF86DGASetViewPort:
2157        return ProcXF86DGASetViewPort(client);
2158    case X_XF86DGAGetVidPage:
2159        return ProcXF86DGAGetVidPage(client);
2160    case X_XF86DGASetVidPage:
2161        return ProcXF86DGASetVidPage(client);
2162    case X_XF86DGAInstallColormap:
2163        return ProcXF86DGAInstallColormap(client);
2164    case X_XF86DGAQueryDirectVideo:
2165        return ProcXF86DGAQueryDirectVideo(client);
2166    case X_XF86DGAViewPortChanged:
2167        return ProcXF86DGAViewPortChanged(client);
2168#endif                          /* DGA_PROTOCOL_OLD_SUPPORT */
2169    default:
2170        return BadRequest;
2171    }
2172}
2173
2174void
2175XFree86DGAExtensionInit(void)
2176{
2177    ExtensionEntry *extEntry;
2178
2179    if (!dixRegisterPrivateKey(&DGAClientPrivateKeyRec, PRIVATE_CLIENT, 0))
2180        return;
2181
2182    if (!dixRegisterPrivateKey(&DGAScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
2183        return;
2184
2185    if ((extEntry = AddExtension(XF86DGANAME,
2186                                 XF86DGANumberEvents,
2187                                 XF86DGANumberErrors,
2188                                 ProcXDGADispatch,
2189                                 SProcXDGADispatch,
2190                                 XDGAResetProc, StandardMinorOpcode))) {
2191        int i;
2192
2193        DGAReqCode = (unsigned char) extEntry->base;
2194        DGAErrorBase = extEntry->errorBase;
2195        DGAEventBase = extEntry->eventBase;
2196        for (i = KeyPress; i <= MotionNotify; i++)
2197            SetCriticalEvent(DGAEventBase + i);
2198    }
2199}
2200