xf86DGA.c revision 6e78d31f
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    REQUEST_SIZE_MATCH(xXDGAOpenFramebufferReq);
1276
1277    if (stuff->screen >= screenInfo.numScreens)
1278        return BadValue;
1279
1280    if (!DGAAvailable(stuff->screen))
1281        return DGAErrorBase + XF86DGANoDirectVideoMode;
1282
1283    rep.type = X_Reply;
1284    rep.length = 0;
1285    rep.sequenceNumber = client->sequence;
1286
1287    if (!DGAOpenFramebuffer(stuff->screen, &deviceName,
1288                            (unsigned char **) (&rep.mem1),
1289                            (int *) &rep.size, (int *) &rep.offset,
1290                            (int *) &rep.extra)) {
1291        return BadAlloc;
1292    }
1293
1294    nameSize = deviceName ? (strlen(deviceName) + 1) : 0;
1295    rep.length = bytes_to_int32(nameSize);
1296
1297    WriteToClient(client, sizeof(xXDGAOpenFramebufferReply), (char *) &rep);
1298    if (rep.length)
1299        WriteToClient(client, nameSize, deviceName);
1300
1301    return Success;
1302}
1303
1304static int
1305ProcXDGACloseFramebuffer(ClientPtr client)
1306{
1307    REQUEST(xXDGACloseFramebufferReq);
1308
1309    REQUEST_SIZE_MATCH(xXDGACloseFramebufferReq);
1310
1311    if (stuff->screen >= screenInfo.numScreens)
1312        return BadValue;
1313
1314    if (!DGAAvailable(stuff->screen))
1315        return DGAErrorBase + XF86DGANoDirectVideoMode;
1316
1317    DGACloseFramebuffer(stuff->screen);
1318
1319    return Success;
1320}
1321
1322static int
1323ProcXDGAQueryModes(ClientPtr client)
1324{
1325    int i, num, size;
1326
1327    REQUEST(xXDGAQueryModesReq);
1328    xXDGAQueryModesReply rep;
1329    xXDGAModeInfo info;
1330    XDGAModePtr mode;
1331
1332    REQUEST_SIZE_MATCH(xXDGAQueryModesReq);
1333
1334    if (stuff->screen >= screenInfo.numScreens)
1335        return BadValue;
1336
1337    rep.type = X_Reply;
1338    rep.length = 0;
1339    rep.number = 0;
1340    rep.sequenceNumber = client->sequence;
1341
1342    if (!DGAAvailable(stuff->screen)) {
1343        rep.number = 0;
1344        rep.length = 0;
1345        WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1346        return Success;
1347    }
1348
1349    if (!(num = DGAGetModes(stuff->screen))) {
1350        WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1351        return Success;
1352    }
1353
1354    if (!(mode = xallocarray(num, sizeof(XDGAModeRec))))
1355        return BadAlloc;
1356
1357    for (i = 0; i < num; i++)
1358        DGAGetModeInfo(stuff->screen, mode + i, i + 1);
1359
1360    size = num * sz_xXDGAModeInfo;
1361    for (i = 0; i < num; i++)
1362        size += pad_to_int32(strlen(mode[i].name) + 1); /* plus NULL */
1363
1364    rep.number = num;
1365    rep.length = bytes_to_int32(size);
1366
1367    WriteToClient(client, sz_xXDGAQueryModesReply, (char *) &rep);
1368
1369    for (i = 0; i < num; i++) {
1370        size = strlen(mode[i].name) + 1;
1371
1372        info.byte_order = mode[i].byteOrder;
1373        info.depth = mode[i].depth;
1374        info.num = mode[i].num;
1375        info.bpp = mode[i].bitsPerPixel;
1376        info.name_size = (size + 3) & ~3L;
1377        info.vsync_num = mode[i].VSync_num;
1378        info.vsync_den = mode[i].VSync_den;
1379        info.flags = mode[i].flags;
1380        info.image_width = mode[i].imageWidth;
1381        info.image_height = mode[i].imageHeight;
1382        info.pixmap_width = mode[i].pixmapWidth;
1383        info.pixmap_height = mode[i].pixmapHeight;
1384        info.bytes_per_scanline = mode[i].bytesPerScanline;
1385        info.red_mask = mode[i].red_mask;
1386        info.green_mask = mode[i].green_mask;
1387        info.blue_mask = mode[i].blue_mask;
1388        info.visual_class = mode[i].visualClass;
1389        info.viewport_width = mode[i].viewportWidth;
1390        info.viewport_height = mode[i].viewportHeight;
1391        info.viewport_xstep = mode[i].xViewportStep;
1392        info.viewport_ystep = mode[i].yViewportStep;
1393        info.viewport_xmax = mode[i].maxViewportX;
1394        info.viewport_ymax = mode[i].maxViewportY;
1395        info.viewport_flags = mode[i].viewportFlags;
1396        info.reserved1 = mode[i].reserved1;
1397        info.reserved2 = mode[i].reserved2;
1398
1399        WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info));
1400        WriteToClient(client, size, mode[i].name);
1401    }
1402
1403    free(mode);
1404
1405    return Success;
1406}
1407
1408static void
1409DGAClientStateChange(CallbackListPtr *pcbl, void *nulldata, void *calldata)
1410{
1411    NewClientInfoRec *pci = (NewClientInfoRec *) calldata;
1412    ClientPtr client = NULL;
1413    int i;
1414
1415    for (i = 0; i < screenInfo.numScreens; i++) {
1416        if (DGA_GETCLIENT(i) == pci->client) {
1417            client = pci->client;
1418            break;
1419        }
1420    }
1421
1422    if (client &&
1423        ((client->clientState == ClientStateGone) ||
1424         (client->clientState == ClientStateRetained))) {
1425        XDGAModeRec mode;
1426        PixmapPtr pPix;
1427
1428        DGA_SETCLIENT(i, NULL);
1429        DGASelectInput(i, NULL, 0);
1430        DGASetMode(i, 0, &mode, &pPix);
1431
1432        if (--DGACallbackRefCount == 0)
1433            DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1434    }
1435}
1436
1437static int
1438ProcXDGASetMode(ClientPtr client)
1439{
1440    REQUEST(xXDGASetModeReq);
1441    xXDGASetModeReply rep;
1442    XDGAModeRec mode;
1443    xXDGAModeInfo info;
1444    PixmapPtr pPix;
1445    ClientPtr owner;
1446    int size;
1447
1448    REQUEST_SIZE_MATCH(xXDGASetModeReq);
1449
1450    if (stuff->screen >= screenInfo.numScreens)
1451        return BadValue;
1452    owner = DGA_GETCLIENT(stuff->screen);
1453
1454    rep.type = X_Reply;
1455    rep.length = 0;
1456    rep.offset = 0;
1457    rep.flags = 0;
1458    rep.sequenceNumber = client->sequence;
1459
1460    if (!DGAAvailable(stuff->screen))
1461        return DGAErrorBase + XF86DGANoDirectVideoMode;
1462
1463    if (owner && owner != client)
1464        return DGAErrorBase + XF86DGANoDirectVideoMode;
1465
1466    if (!stuff->mode) {
1467        if (owner) {
1468            if (--DGACallbackRefCount == 0)
1469                DeleteCallback(&ClientStateCallback, DGAClientStateChange,
1470                               NULL);
1471        }
1472        DGA_SETCLIENT(stuff->screen, NULL);
1473        DGASelectInput(stuff->screen, NULL, 0);
1474        DGASetMode(stuff->screen, 0, &mode, &pPix);
1475        WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep);
1476        return Success;
1477    }
1478
1479    if (Success != DGASetMode(stuff->screen, stuff->mode, &mode, &pPix))
1480        return BadValue;
1481
1482    if (!owner) {
1483        if (DGACallbackRefCount++ == 0)
1484            AddCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1485    }
1486
1487    DGA_SETCLIENT(stuff->screen, client);
1488
1489    if (pPix) {
1490        if (AddResource(stuff->pid, RT_PIXMAP, (void *) (pPix))) {
1491            pPix->drawable.id = (int) stuff->pid;
1492            rep.flags = DGA_PIXMAP_AVAILABLE;
1493        }
1494    }
1495
1496    size = strlen(mode.name) + 1;
1497
1498    info.byte_order = mode.byteOrder;
1499    info.depth = mode.depth;
1500    info.num = mode.num;
1501    info.bpp = mode.bitsPerPixel;
1502    info.name_size = (size + 3) & ~3L;
1503    info.vsync_num = mode.VSync_num;
1504    info.vsync_den = mode.VSync_den;
1505    info.flags = mode.flags;
1506    info.image_width = mode.imageWidth;
1507    info.image_height = mode.imageHeight;
1508    info.pixmap_width = mode.pixmapWidth;
1509    info.pixmap_height = mode.pixmapHeight;
1510    info.bytes_per_scanline = mode.bytesPerScanline;
1511    info.red_mask = mode.red_mask;
1512    info.green_mask = mode.green_mask;
1513    info.blue_mask = mode.blue_mask;
1514    info.visual_class = mode.visualClass;
1515    info.viewport_width = mode.viewportWidth;
1516    info.viewport_height = mode.viewportHeight;
1517    info.viewport_xstep = mode.xViewportStep;
1518    info.viewport_ystep = mode.yViewportStep;
1519    info.viewport_xmax = mode.maxViewportX;
1520    info.viewport_ymax = mode.maxViewportY;
1521    info.viewport_flags = mode.viewportFlags;
1522    info.reserved1 = mode.reserved1;
1523    info.reserved2 = mode.reserved2;
1524
1525    rep.length = bytes_to_int32(sz_xXDGAModeInfo + info.name_size);
1526
1527    WriteToClient(client, sz_xXDGASetModeReply, (char *) &rep);
1528    WriteToClient(client, sz_xXDGAModeInfo, (char *) (&info));
1529    WriteToClient(client, size, mode.name);
1530
1531    return Success;
1532}
1533
1534static int
1535ProcXDGASetViewport(ClientPtr client)
1536{
1537    REQUEST(xXDGASetViewportReq);
1538
1539    REQUEST_SIZE_MATCH(xXDGASetViewportReq);
1540
1541    if (stuff->screen >= screenInfo.numScreens)
1542        return BadValue;
1543
1544    if (DGA_GETCLIENT(stuff->screen) != client)
1545        return DGAErrorBase + XF86DGADirectNotActivated;
1546
1547    DGASetViewport(stuff->screen, stuff->x, stuff->y, stuff->flags);
1548
1549    return Success;
1550}
1551
1552static int
1553ProcXDGAInstallColormap(ClientPtr client)
1554{
1555    ColormapPtr cmap;
1556    int rc;
1557
1558    REQUEST(xXDGAInstallColormapReq);
1559
1560    REQUEST_SIZE_MATCH(xXDGAInstallColormapReq);
1561
1562    if (stuff->screen >= screenInfo.numScreens)
1563        return BadValue;
1564
1565    if (DGA_GETCLIENT(stuff->screen) != client)
1566        return DGAErrorBase + XF86DGADirectNotActivated;
1567
1568    rc = dixLookupResourceByType((void **) &cmap, stuff->cmap, RT_COLORMAP,
1569                                 client, DixInstallAccess);
1570    if (rc != Success)
1571        return rc;
1572    DGAInstallCmap(cmap);
1573    return Success;
1574}
1575
1576static int
1577ProcXDGASelectInput(ClientPtr client)
1578{
1579    REQUEST(xXDGASelectInputReq);
1580
1581    REQUEST_SIZE_MATCH(xXDGASelectInputReq);
1582
1583    if (stuff->screen >= screenInfo.numScreens)
1584        return BadValue;
1585
1586    if (DGA_GETCLIENT(stuff->screen) != client)
1587        return DGAErrorBase + XF86DGADirectNotActivated;
1588
1589    if (DGA_GETCLIENT(stuff->screen) == client)
1590        DGASelectInput(stuff->screen, client, stuff->mask);
1591
1592    return Success;
1593}
1594
1595static int
1596ProcXDGAFillRectangle(ClientPtr client)
1597{
1598    REQUEST(xXDGAFillRectangleReq);
1599
1600    REQUEST_SIZE_MATCH(xXDGAFillRectangleReq);
1601
1602    if (stuff->screen >= screenInfo.numScreens)
1603        return BadValue;
1604
1605    if (DGA_GETCLIENT(stuff->screen) != client)
1606        return DGAErrorBase + XF86DGADirectNotActivated;
1607
1608    if (Success != DGAFillRect(stuff->screen, stuff->x, stuff->y,
1609                               stuff->width, stuff->height, stuff->color))
1610        return BadMatch;
1611
1612    return Success;
1613}
1614
1615static int
1616ProcXDGACopyArea(ClientPtr client)
1617{
1618    REQUEST(xXDGACopyAreaReq);
1619
1620    REQUEST_SIZE_MATCH(xXDGACopyAreaReq);
1621
1622    if (stuff->screen >= screenInfo.numScreens)
1623        return BadValue;
1624
1625    if (DGA_GETCLIENT(stuff->screen) != client)
1626        return DGAErrorBase + XF86DGADirectNotActivated;
1627
1628    if (Success != DGABlitRect(stuff->screen, stuff->srcx, stuff->srcy,
1629                               stuff->width, stuff->height, stuff->dstx,
1630                               stuff->dsty))
1631        return BadMatch;
1632
1633    return Success;
1634}
1635
1636static int
1637ProcXDGACopyTransparentArea(ClientPtr client)
1638{
1639    REQUEST(xXDGACopyTransparentAreaReq);
1640
1641    REQUEST_SIZE_MATCH(xXDGACopyTransparentAreaReq);
1642
1643    if (stuff->screen >= screenInfo.numScreens)
1644        return BadValue;
1645
1646    if (DGA_GETCLIENT(stuff->screen) != client)
1647        return DGAErrorBase + XF86DGADirectNotActivated;
1648
1649    if (Success != DGABlitTransRect(stuff->screen, stuff->srcx, stuff->srcy,
1650                                    stuff->width, stuff->height, stuff->dstx,
1651                                    stuff->dsty, stuff->key))
1652        return BadMatch;
1653
1654    return Success;
1655}
1656
1657static int
1658ProcXDGAGetViewportStatus(ClientPtr client)
1659{
1660    REQUEST(xXDGAGetViewportStatusReq);
1661    xXDGAGetViewportStatusReply rep;
1662
1663    REQUEST_SIZE_MATCH(xXDGAGetViewportStatusReq);
1664
1665    if (stuff->screen >= screenInfo.numScreens)
1666        return BadValue;
1667
1668    if (DGA_GETCLIENT(stuff->screen) != client)
1669        return DGAErrorBase + XF86DGADirectNotActivated;
1670
1671    rep.type = X_Reply;
1672    rep.length = 0;
1673    rep.sequenceNumber = client->sequence;
1674
1675    rep.status = DGAGetViewportStatus(stuff->screen);
1676
1677    WriteToClient(client, sizeof(xXDGAGetViewportStatusReply), (char *) &rep);
1678    return Success;
1679}
1680
1681static int
1682ProcXDGASync(ClientPtr client)
1683{
1684    REQUEST(xXDGASyncReq);
1685    xXDGASyncReply rep;
1686
1687    REQUEST_SIZE_MATCH(xXDGASyncReq);
1688
1689    if (stuff->screen >= screenInfo.numScreens)
1690        return BadValue;
1691
1692    if (DGA_GETCLIENT(stuff->screen) != client)
1693        return DGAErrorBase + XF86DGADirectNotActivated;
1694
1695    rep.type = X_Reply;
1696    rep.length = 0;
1697    rep.sequenceNumber = client->sequence;
1698
1699    DGASync(stuff->screen);
1700
1701    WriteToClient(client, sizeof(xXDGASyncReply), (char *) &rep);
1702    return Success;
1703}
1704
1705static int
1706ProcXDGASetClientVersion(ClientPtr client)
1707{
1708    REQUEST(xXDGASetClientVersionReq);
1709
1710    DGAPrivPtr pPriv;
1711
1712    REQUEST_SIZE_MATCH(xXDGASetClientVersionReq);
1713    if ((pPriv = DGA_GETPRIV(client)) == NULL) {
1714        pPriv = malloc(sizeof(DGAPrivRec));
1715        /* XXX Need to look into freeing this */
1716        if (!pPriv)
1717            return BadAlloc;
1718        DGA_SETPRIV(client, pPriv);
1719    }
1720    pPriv->major = stuff->major;
1721    pPriv->minor = stuff->minor;
1722
1723    return Success;
1724}
1725
1726static int
1727ProcXDGAChangePixmapMode(ClientPtr client)
1728{
1729    REQUEST(xXDGAChangePixmapModeReq);
1730    xXDGAChangePixmapModeReply rep;
1731    int x, y;
1732
1733    REQUEST_SIZE_MATCH(xXDGAChangePixmapModeReq);
1734
1735    if (stuff->screen >= screenInfo.numScreens)
1736        return BadValue;
1737
1738    if (DGA_GETCLIENT(stuff->screen) != client)
1739        return DGAErrorBase + XF86DGADirectNotActivated;
1740
1741    rep.type = X_Reply;
1742    rep.length = 0;
1743    rep.sequenceNumber = client->sequence;
1744
1745    x = stuff->x;
1746    y = stuff->y;
1747
1748    if (!DGAChangePixmapMode(stuff->screen, &x, &y, stuff->flags))
1749        return BadMatch;
1750
1751    rep.x = x;
1752    rep.y = y;
1753    WriteToClient(client, sizeof(xXDGAChangePixmapModeReply), (char *) &rep);
1754
1755    return Success;
1756}
1757
1758static int
1759ProcXDGACreateColormap(ClientPtr client)
1760{
1761    REQUEST(xXDGACreateColormapReq);
1762    int result;
1763
1764    REQUEST_SIZE_MATCH(xXDGACreateColormapReq);
1765
1766    if (stuff->screen >= screenInfo.numScreens)
1767        return BadValue;
1768
1769    if (DGA_GETCLIENT(stuff->screen) != client)
1770        return DGAErrorBase + XF86DGADirectNotActivated;
1771
1772    if (!stuff->mode)
1773        return BadValue;
1774
1775    result = DGACreateColormap(stuff->screen, client, stuff->id,
1776                               stuff->mode, stuff->alloc);
1777    if (result != Success)
1778        return result;
1779
1780    return Success;
1781}
1782
1783/*
1784 *
1785 * Support for the old DGA protocol, used to live in xf86dga.c
1786 *
1787 */
1788
1789#ifdef DGA_PROTOCOL_OLD_SUPPORT
1790
1791static int
1792ProcXF86DGAGetVideoLL(ClientPtr client)
1793{
1794    REQUEST(xXF86DGAGetVideoLLReq);
1795    xXF86DGAGetVideoLLReply rep;
1796    XDGAModeRec mode;
1797    int num, offset, flags;
1798    char *name;
1799
1800    REQUEST_SIZE_MATCH(xXF86DGAGetVideoLLReq);
1801
1802    if (stuff->screen >= screenInfo.numScreens)
1803        return BadValue;
1804
1805    rep.type = X_Reply;
1806    rep.length = 0;
1807    rep.sequenceNumber = client->sequence;
1808
1809    if (!DGAAvailable(stuff->screen))
1810        return DGAErrorBase + XF86DGANoDirectVideoMode;
1811
1812    if (!(num = DGAGetOldDGAMode(stuff->screen)))
1813        return DGAErrorBase + XF86DGANoDirectVideoMode;
1814
1815    /* get the parameters for the mode that best matches */
1816    DGAGetModeInfo(stuff->screen, &mode, num);
1817
1818    if (!DGAOpenFramebuffer(stuff->screen, &name,
1819                            (unsigned char **) (&rep.offset),
1820                            (int *) (&rep.bank_size), &offset, &flags))
1821        return BadAlloc;
1822
1823    rep.offset += mode.offset;
1824    rep.width = mode.bytesPerScanline / (mode.bitsPerPixel >> 3);
1825    rep.ram_size = rep.bank_size >> 10;
1826
1827    WriteToClient(client, SIZEOF(xXF86DGAGetVideoLLReply), (char *) &rep);
1828    return Success;
1829}
1830
1831static int
1832ProcXF86DGADirectVideo(ClientPtr client)
1833{
1834    int num;
1835    PixmapPtr pix;
1836    XDGAModeRec mode;
1837    ClientPtr owner;
1838
1839    REQUEST(xXF86DGADirectVideoReq);
1840
1841    REQUEST_SIZE_MATCH(xXF86DGADirectVideoReq);
1842
1843    if (stuff->screen >= screenInfo.numScreens)
1844        return BadValue;
1845
1846    if (!DGAAvailable(stuff->screen))
1847        return DGAErrorBase + XF86DGANoDirectVideoMode;
1848
1849    owner = DGA_GETCLIENT(stuff->screen);
1850
1851    if (owner && owner != client)
1852        return DGAErrorBase + XF86DGANoDirectVideoMode;
1853
1854    if (stuff->enable & XF86DGADirectGraphics) {
1855        if (!(num = DGAGetOldDGAMode(stuff->screen)))
1856            return DGAErrorBase + XF86DGANoDirectVideoMode;
1857    }
1858    else
1859        num = 0;
1860
1861    if (Success != DGASetMode(stuff->screen, num, &mode, &pix))
1862        return DGAErrorBase + XF86DGAScreenNotActive;
1863
1864    DGASetInputMode(stuff->screen,
1865                    (stuff->enable & XF86DGADirectKeyb) != 0,
1866                    (stuff->enable & XF86DGADirectMouse) != 0);
1867
1868    /* We need to track the client and attach the teardown callback */
1869    if (stuff->enable &
1870        (XF86DGADirectGraphics | XF86DGADirectKeyb | XF86DGADirectMouse)) {
1871        if (!owner) {
1872            if (DGACallbackRefCount++ == 0)
1873                AddCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1874        }
1875
1876        DGA_SETCLIENT(stuff->screen, client);
1877    }
1878    else {
1879        if (owner) {
1880            if (--DGACallbackRefCount == 0)
1881                DeleteCallback(&ClientStateCallback, DGAClientStateChange,
1882                               NULL);
1883        }
1884
1885        DGA_SETCLIENT(stuff->screen, NULL);
1886    }
1887
1888    return Success;
1889}
1890
1891static int
1892ProcXF86DGAGetViewPortSize(ClientPtr client)
1893{
1894    int num;
1895    XDGAModeRec mode;
1896
1897    REQUEST(xXF86DGAGetViewPortSizeReq);
1898    xXF86DGAGetViewPortSizeReply rep;
1899
1900    REQUEST_SIZE_MATCH(xXF86DGAGetViewPortSizeReq);
1901
1902    if (stuff->screen >= screenInfo.numScreens)
1903        return BadValue;
1904
1905    rep.type = X_Reply;
1906    rep.length = 0;
1907    rep.sequenceNumber = client->sequence;
1908
1909    if (!DGAAvailable(stuff->screen))
1910        return DGAErrorBase + XF86DGANoDirectVideoMode;
1911
1912    if (!(num = DGAGetOldDGAMode(stuff->screen)))
1913        return DGAErrorBase + XF86DGANoDirectVideoMode;
1914
1915    DGAGetModeInfo(stuff->screen, &mode, num);
1916
1917    rep.width = mode.viewportWidth;
1918    rep.height = mode.viewportHeight;
1919
1920    WriteToClient(client, SIZEOF(xXF86DGAGetViewPortSizeReply), (char *) &rep);
1921    return Success;
1922}
1923
1924static int
1925ProcXF86DGASetViewPort(ClientPtr client)
1926{
1927    REQUEST(xXF86DGASetViewPortReq);
1928
1929    REQUEST_SIZE_MATCH(xXF86DGASetViewPortReq);
1930
1931    if (stuff->screen >= screenInfo.numScreens)
1932        return BadValue;
1933
1934    if (DGA_GETCLIENT(stuff->screen) != client)
1935        return DGAErrorBase + XF86DGADirectNotActivated;
1936
1937    if (!DGAAvailable(stuff->screen))
1938        return DGAErrorBase + XF86DGANoDirectVideoMode;
1939
1940    if (!DGAActive(stuff->screen))
1941        return DGAErrorBase + XF86DGADirectNotActivated;
1942
1943    if (DGASetViewport(stuff->screen, stuff->x, stuff->y, DGA_FLIP_RETRACE)
1944        != Success)
1945        return DGAErrorBase + XF86DGADirectNotActivated;
1946
1947    return Success;
1948}
1949
1950static int
1951ProcXF86DGAGetVidPage(ClientPtr client)
1952{
1953    REQUEST(xXF86DGAGetVidPageReq);
1954    xXF86DGAGetVidPageReply rep;
1955
1956    REQUEST_SIZE_MATCH(xXF86DGAGetVidPageReq);
1957
1958    if (stuff->screen >= screenInfo.numScreens)
1959        return BadValue;
1960
1961    rep.type = X_Reply;
1962    rep.length = 0;
1963    rep.sequenceNumber = client->sequence;
1964    rep.vpage = 0;              /* silently fail */
1965
1966    WriteToClient(client, SIZEOF(xXF86DGAGetVidPageReply), (char *) &rep);
1967    return Success;
1968}
1969
1970static int
1971ProcXF86DGASetVidPage(ClientPtr client)
1972{
1973    REQUEST(xXF86DGASetVidPageReq);
1974
1975    REQUEST_SIZE_MATCH(xXF86DGASetVidPageReq);
1976
1977    if (stuff->screen >= screenInfo.numScreens)
1978        return BadValue;
1979
1980    /* silently fail */
1981
1982    return Success;
1983}
1984
1985static int
1986ProcXF86DGAInstallColormap(ClientPtr client)
1987{
1988    ColormapPtr pcmp;
1989    int rc;
1990
1991    REQUEST(xXF86DGAInstallColormapReq);
1992
1993    REQUEST_SIZE_MATCH(xXF86DGAInstallColormapReq);
1994
1995    if (stuff->screen >= screenInfo.numScreens)
1996        return BadValue;
1997
1998    if (DGA_GETCLIENT(stuff->screen) != client)
1999        return DGAErrorBase + XF86DGADirectNotActivated;
2000
2001    if (!DGAActive(stuff->screen))
2002        return DGAErrorBase + XF86DGADirectNotActivated;
2003
2004    rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2005                                 client, DixInstallAccess);
2006    if (rc == Success) {
2007        DGAInstallCmap(pcmp);
2008        return Success;
2009    }
2010    else {
2011        return rc;
2012    }
2013}
2014
2015static int
2016ProcXF86DGAQueryDirectVideo(ClientPtr client)
2017{
2018    REQUEST(xXF86DGAQueryDirectVideoReq);
2019    xXF86DGAQueryDirectVideoReply rep;
2020
2021    REQUEST_SIZE_MATCH(xXF86DGAQueryDirectVideoReq);
2022
2023    if (stuff->screen >= screenInfo.numScreens)
2024        return BadValue;
2025
2026    rep.type = X_Reply;
2027    rep.length = 0;
2028    rep.sequenceNumber = client->sequence;
2029    rep.flags = 0;
2030
2031    if (DGAAvailable(stuff->screen))
2032        rep.flags = XF86DGADirectPresent;
2033
2034    WriteToClient(client, SIZEOF(xXF86DGAQueryDirectVideoReply), (char *) &rep);
2035    return Success;
2036}
2037
2038static int
2039ProcXF86DGAViewPortChanged(ClientPtr client)
2040{
2041    REQUEST(xXF86DGAViewPortChangedReq);
2042    xXF86DGAViewPortChangedReply rep;
2043
2044    REQUEST_SIZE_MATCH(xXF86DGAViewPortChangedReq);
2045
2046    if (stuff->screen >= screenInfo.numScreens)
2047        return BadValue;
2048
2049    if (DGA_GETCLIENT(stuff->screen) != client)
2050        return DGAErrorBase + XF86DGADirectNotActivated;
2051
2052    if (!DGAActive(stuff->screen))
2053        return DGAErrorBase + XF86DGADirectNotActivated;
2054
2055    rep.type = X_Reply;
2056    rep.length = 0;
2057    rep.sequenceNumber = client->sequence;
2058    rep.result = 1;
2059
2060    WriteToClient(client, SIZEOF(xXF86DGAViewPortChangedReply), (char *) &rep);
2061    return Success;
2062}
2063
2064#endif                          /* DGA_PROTOCOL_OLD_SUPPORT */
2065
2066static int
2067SProcXDGADispatch(ClientPtr client)
2068{
2069    return DGAErrorBase + XF86DGAClientNotLocal;
2070}
2071
2072#if 0
2073#define DGA_REQ_DEBUG
2074#endif
2075
2076#ifdef DGA_REQ_DEBUG
2077static char *dgaMinor[] = {
2078    "QueryVersion",
2079    "GetVideoLL",
2080    "DirectVideo",
2081    "GetViewPortSize",
2082    "SetViewPort",
2083    "GetVidPage",
2084    "SetVidPage",
2085    "InstallColormap",
2086    "QueryDirectVideo",
2087    "ViewPortChanged",
2088    "10",
2089    "11",
2090    "QueryModes",
2091    "SetMode",
2092    "SetViewport",
2093    "InstallColormap",
2094    "SelectInput",
2095    "FillRectangle",
2096    "CopyArea",
2097    "CopyTransparentArea",
2098    "GetViewportStatus",
2099    "Sync",
2100    "OpenFramebuffer",
2101    "CloseFramebuffer",
2102    "SetClientVersion",
2103    "ChangePixmapMode",
2104    "CreateColormap",
2105};
2106#endif
2107
2108static int
2109ProcXDGADispatch(ClientPtr client)
2110{
2111    REQUEST(xReq);
2112
2113    if (!client->local)
2114        return DGAErrorBase + XF86DGAClientNotLocal;
2115
2116#ifdef DGA_REQ_DEBUG
2117    if (stuff->data <= X_XDGACreateColormap)
2118        fprintf(stderr, "    DGA %s\n", dgaMinor[stuff->data]);
2119#endif
2120
2121    switch (stuff->data) {
2122        /*
2123         * DGA2 Protocol
2124         */
2125    case X_XDGAQueryVersion:
2126        return ProcXDGAQueryVersion(client);
2127    case X_XDGAQueryModes:
2128        return ProcXDGAQueryModes(client);
2129    case X_XDGASetMode:
2130        return ProcXDGASetMode(client);
2131    case X_XDGAOpenFramebuffer:
2132        return ProcXDGAOpenFramebuffer(client);
2133    case X_XDGACloseFramebuffer:
2134        return ProcXDGACloseFramebuffer(client);
2135    case X_XDGASetViewport:
2136        return ProcXDGASetViewport(client);
2137    case X_XDGAInstallColormap:
2138        return ProcXDGAInstallColormap(client);
2139    case X_XDGASelectInput:
2140        return ProcXDGASelectInput(client);
2141    case X_XDGAFillRectangle:
2142        return ProcXDGAFillRectangle(client);
2143    case X_XDGACopyArea:
2144        return ProcXDGACopyArea(client);
2145    case X_XDGACopyTransparentArea:
2146        return ProcXDGACopyTransparentArea(client);
2147    case X_XDGAGetViewportStatus:
2148        return ProcXDGAGetViewportStatus(client);
2149    case X_XDGASync:
2150        return ProcXDGASync(client);
2151    case X_XDGASetClientVersion:
2152        return ProcXDGASetClientVersion(client);
2153    case X_XDGAChangePixmapMode:
2154        return ProcXDGAChangePixmapMode(client);
2155    case X_XDGACreateColormap:
2156        return ProcXDGACreateColormap(client);
2157        /*
2158         * Old DGA Protocol
2159         */
2160#ifdef DGA_PROTOCOL_OLD_SUPPORT
2161    case X_XF86DGAGetVideoLL:
2162        return ProcXF86DGAGetVideoLL(client);
2163    case X_XF86DGADirectVideo:
2164        return ProcXF86DGADirectVideo(client);
2165    case X_XF86DGAGetViewPortSize:
2166        return ProcXF86DGAGetViewPortSize(client);
2167    case X_XF86DGASetViewPort:
2168        return ProcXF86DGASetViewPort(client);
2169    case X_XF86DGAGetVidPage:
2170        return ProcXF86DGAGetVidPage(client);
2171    case X_XF86DGASetVidPage:
2172        return ProcXF86DGASetVidPage(client);
2173    case X_XF86DGAInstallColormap:
2174        return ProcXF86DGAInstallColormap(client);
2175    case X_XF86DGAQueryDirectVideo:
2176        return ProcXF86DGAQueryDirectVideo(client);
2177    case X_XF86DGAViewPortChanged:
2178        return ProcXF86DGAViewPortChanged(client);
2179#endif                          /* DGA_PROTOCOL_OLD_SUPPORT */
2180    default:
2181        return BadRequest;
2182    }
2183}
2184
2185void
2186XFree86DGAExtensionInit(void)
2187{
2188    ExtensionEntry *extEntry;
2189
2190    if (!dixRegisterPrivateKey(&DGAClientPrivateKeyRec, PRIVATE_CLIENT, 0))
2191        return;
2192
2193    if (!dixRegisterPrivateKey(&DGAScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
2194        return;
2195
2196    if ((extEntry = AddExtension(XF86DGANAME,
2197                                 XF86DGANumberEvents,
2198                                 XF86DGANumberErrors,
2199                                 ProcXDGADispatch,
2200                                 SProcXDGADispatch,
2201                                 XDGAResetProc, StandardMinorOpcode))) {
2202        int i;
2203
2204        DGAReqCode = (unsigned char) extEntry->base;
2205        DGAErrorBase = extEntry->errorBase;
2206        DGAEventBase = extEntry->eventBase;
2207        for (i = KeyPress; i <= MotionNotify; i++)
2208            SetCriticalEvent(DGAEventBase + i);
2209    }
2210}
2211