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