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 static Bool mieq_installed;
85 
86 static Bool DGACloseScreen(ScreenPtr pScreen);
87 static void DGADestroyColormap(ColormapPtr pmap);
88 static void DGAInstallColormap(ColormapPtr pmap);
89 static void DGAUninstallColormap(ColormapPtr pmap);
90 static void DGAHandleEvent(int screen_num, InternalEvent *event,
91                            DeviceIntPtr device);
92 
93 static void
94  DGACopyModeInfo(DGAModePtr mode, XDGAModePtr xmode);
95 
96 static unsigned char DGAReqCode = 0;
97 static int DGAErrorBase;
98 static int DGAEventBase;
99 
100 #define DGA_GET_SCREEN_PRIV(pScreen) ((DGAScreenPtr) \
101     dixLookupPrivate(&(pScreen)->devPrivates, &DGAScreenKeyRec))
102 
103 typedef struct _FakedVisualList {
104     Bool free;
105     VisualPtr pVisual;
106     struct _FakedVisualList *next;
107 } FakedVisualList;
108 
109 typedef 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 
129 Bool
DGAInit(ScreenPtr pScreen,DGAFunctionPtr funcs,DGAModePtr modes,int num)130 DGAInit(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 
191 Bool
DGAReInitModes(ScreenPtr pScreen,DGAModePtr modes,int num)192 DGAReInitModes(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 
236 static void
FreeMarkedVisuals(ScreenPtr pScreen)237 FreeMarkedVisuals(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 
266 static Bool
DGACloseScreen(ScreenPtr pScreen)267 DGACloseScreen(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 
291 static void
DGADestroyColormap(ColormapPtr pmap)292 DGADestroyColormap(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 
319 static void
DGAInstallColormap(ColormapPtr pmap)320 DGAInstallColormap(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 
337 static void
DGAUninstallColormap(ColormapPtr pmap)338 DGAUninstallColormap(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 
354 int
xf86SetDGAMode(ScrnInfoPtr pScrn,int num,DGADevicePtr devRet)355 xf86SetDGAMode(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 
474 static void
DGASetInputMode(int index,Bool keyboard,Bool mouse)475 DGASetInputMode(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 
491 static Bool
DGAChangePixmapMode(int index,int * x,int * y,int mode)492 DGAChangePixmapMode(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 
552 Bool
DGAScreenAvailable(ScreenPtr pScreen)553 DGAScreenAvailable(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 
563 static Bool
DGAAvailable(int index)564 DGAAvailable(int index)
565 {
566     ScreenPtr pScreen;
567 
568     assert(index < MAXSCREENS);
569     pScreen = screenInfo.screens[index];
570     return DGAScreenAvailable(pScreen);
571 }
572 
573 Bool
DGAActive(int index)574 DGAActive(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 
591 void
DGAShutdown(void)592 DGAShutdown(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 
609 static int
DGASetMode(int index,int num,XDGAModePtr mode,PixmapPtr * pPix)610 DGASetMode(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 
629 static void
DGASelectInput(int index,ClientPtr client,long mask)630 DGASelectInput(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 
639 static int
DGAGetViewportStatus(int index)640 DGAGetViewportStatus(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 
652 static int
DGASetViewport(int index,int x,int y,int mode)653 DGASetViewport(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 
662 static int
BitsClear(CARD32 data)663 BitsClear(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 
678 static int
DGACreateColormap(int index,ClientPtr client,int id,int mode,int alloc)679 DGACreateColormap(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 
747 static void
DGAInstallCmap(ColormapPtr cmap)748 DGAInstallCmap(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 
763 static int
DGASync(int index)764 DGASync(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 
776 static int
DGAFillRect(int index,int x,int y,int w,int h,unsigned long color)777 DGAFillRect(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 
792 static int
DGABlitRect(int index,int srcx,int srcy,int w,int h,int dstx,int dsty)793 DGABlitRect(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 
809 static int
DGABlitTransRect(int index,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long color)810 DGABlitTransRect(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 
829 static int
DGAGetModes(int index)830 DGAGetModes(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 
839 static int
DGAGetModeInfo(int index,XDGAModePtr mode,int num)840 DGAGetModeInfo(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 
854 static void
DGACopyModeInfo(DGAModePtr mode,XDGAModePtr xmode)855 DGACopyModeInfo(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 
893 Bool
DGAVTSwitch(void)894 DGAVTSwitch(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 
915 Bool
DGAStealKeyEvent(DeviceIntPtr dev,int index,int key_code,int is_down)916 DGAStealKeyEvent(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 
947 Bool
DGAStealMotionEvent(DeviceIntPtr dev,int index,int dx,int dy)948 DGAStealMotionEvent(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 
975 Bool
DGAStealButtonEvent(DeviceIntPtr dev,int index,int button,int is_down)976 DGAStealButtonEvent(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 */
1007 static 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 
1017 static void
DGAProcessKeyboardEvent(ScreenPtr pScreen,DGAEvent * event,DeviceIntPtr keybd)1018 DGAProcessKeyboardEvent(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 
1071 static void
DGAProcessPointerEvent(ScreenPtr pScreen,DGAEvent * event,DeviceIntPtr mouse)1072 DGAProcessPointerEvent(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 
1129 static Bool
DGAOpenFramebuffer(int index,char ** name,unsigned char ** mem,int * size,int * offset,int * flags)1130 DGAOpenFramebuffer(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 
1143 static void
DGACloseFramebuffer(int index)1144 DGACloseFramebuffer(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 
1155 static int
DGAGetOldDGAMode(int index)1156 DGAGetOldDGAMode(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 
1184 static void
DGAHandleEvent(int screen_num,InternalEvent * ev,DeviceIntPtr device)1185 DGAHandleEvent(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 
1215 static void XDGAResetProc(ExtensionEntry * extEntry);
1216 
1217 static void DGAClientStateChange(CallbackListPtr *, void *, void *);
1218 
1219 static DevPrivateKeyRec DGAScreenPrivateKeyRec;
1220 
1221 #define DGAScreenPrivateKey (&DGAScreenPrivateKeyRec)
1222 #define DGAScreenPrivateKeyRegistered (DGAScreenPrivateKeyRec.initialized)
1223 static DevPrivateKeyRec DGAClientPrivateKeyRec;
1224 
1225 #define DGAClientPrivateKey (&DGAClientPrivateKeyRec)
1226 static int DGACallbackRefCount = 0;
1227 
1228 /* This holds the client's version information */
1229 typedef 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 
1244 static void
XDGAResetProc(ExtensionEntry * extEntry)1245 XDGAResetProc(ExtensionEntry * extEntry)
1246 {
1247     DeleteCallback(&ClientStateCallback, DGAClientStateChange, NULL);
1248     DGACallbackRefCount = 0;
1249 }
1250 
1251 static int
ProcXDGAQueryVersion(ClientPtr client)1252 ProcXDGAQueryVersion(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 
1267 static int
ProcXDGAOpenFramebuffer(ClientPtr client)1268 ProcXDGAOpenFramebuffer(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 
1304 static int
ProcXDGACloseFramebuffer(ClientPtr client)1305 ProcXDGACloseFramebuffer(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 
1322 static int
ProcXDGAQueryModes(ClientPtr client)1323 ProcXDGAQueryModes(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 
1408 static void
DGAClientStateChange(CallbackListPtr * pcbl,void * nulldata,void * calldata)1409 DGAClientStateChange(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 
1437 static int
ProcXDGASetMode(ClientPtr client)1438 ProcXDGASetMode(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 
1534 static int
ProcXDGASetViewport(ClientPtr client)1535 ProcXDGASetViewport(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 
1552 static int
ProcXDGAInstallColormap(ClientPtr client)1553 ProcXDGAInstallColormap(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 
1576 static int
ProcXDGASelectInput(ClientPtr client)1577 ProcXDGASelectInput(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 
1595 static int
ProcXDGAFillRectangle(ClientPtr client)1596 ProcXDGAFillRectangle(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 
1615 static int
ProcXDGACopyArea(ClientPtr client)1616 ProcXDGACopyArea(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 
1636 static int
ProcXDGACopyTransparentArea(ClientPtr client)1637 ProcXDGACopyTransparentArea(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 
1657 static int
ProcXDGAGetViewportStatus(ClientPtr client)1658 ProcXDGAGetViewportStatus(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 
1681 static int
ProcXDGASync(ClientPtr client)1682 ProcXDGASync(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 
1705 static int
ProcXDGASetClientVersion(ClientPtr client)1706 ProcXDGASetClientVersion(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 
1726 static int
ProcXDGAChangePixmapMode(ClientPtr client)1727 ProcXDGAChangePixmapMode(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 
1758 static int
ProcXDGACreateColormap(ClientPtr client)1759 ProcXDGACreateColormap(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 
1791 static int
ProcXF86DGAGetVideoLL(ClientPtr client)1792 ProcXF86DGAGetVideoLL(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 
1831 static int
ProcXF86DGADirectVideo(ClientPtr client)1832 ProcXF86DGADirectVideo(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 
1891 static int
ProcXF86DGAGetViewPortSize(ClientPtr client)1892 ProcXF86DGAGetViewPortSize(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 
1924 static int
ProcXF86DGASetViewPort(ClientPtr client)1925 ProcXF86DGASetViewPort(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 
1950 static int
ProcXF86DGAGetVidPage(ClientPtr client)1951 ProcXF86DGAGetVidPage(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 
1970 static int
ProcXF86DGASetVidPage(ClientPtr client)1971 ProcXF86DGASetVidPage(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 
1985 static int
ProcXF86DGAInstallColormap(ClientPtr client)1986 ProcXF86DGAInstallColormap(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 
2015 static int
ProcXF86DGAQueryDirectVideo(ClientPtr client)2016 ProcXF86DGAQueryDirectVideo(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 
2038 static int
ProcXF86DGAViewPortChanged(ClientPtr client)2039 ProcXF86DGAViewPortChanged(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 
2066 static int _X_COLD
SProcXDGADispatch(ClientPtr client)2067 SProcXDGADispatch(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
2077 static 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 
2108 static int
ProcXDGADispatch(ClientPtr client)2109 ProcXDGADispatch(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 
2185 void
XFree86DGAExtensionInit(void)2186 XFree86DGAExtensionInit(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