xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86DGA.c (59980B)


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