xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/dri2/dri2ext.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright © 2008 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Soft-
6  * ware"), to deal in the Software without restriction, including without
7  * limitation the rights to use, copy, modify, merge, publish, distribute,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, provided that the above copyright
10  * notice(s) and this permission notice appear in all copies of the Soft-
11  * ware and that both the above copyright notice(s) and this permission
12  * notice appear in supporting documentation.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16  * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17  * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18  * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19  * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22  * MANCE OF THIS SOFTWARE.
23  *
24  * Except as contained in this notice, the name of a copyright holder shall
25  * not be used in advertising or otherwise to promote the sale, use or
26  * other dealings in this Software without prior written authorization of
27  * the copyright holder.
28  *
29  * Authors:
30  *   Kristian Høgsberg (krh@redhat.com)
31  */
32 
33 #ifdef HAVE_XORG_CONFIG_H
34 #include <xorg-config.h>
35 #endif
36 
37 #include <X11/X.h>
38 #include <X11/Xproto.h>
39 #include <X11/extensions/dri2proto.h>
40 #include <X11/extensions/xfixeswire.h>
41 #include "dixstruct.h"
42 #include "scrnintstr.h"
43 #include "pixmapstr.h"
44 #include "extnsionst.h"
45 #include "xfixes.h"
46 #include "dri2.h"
47 #include "dri2int.h"
48 #include "protocol-versions.h"
49 
50 /* The only xf86 includes */
51 #include "xf86Module.h"
52 #include "xf86Extensions.h"
53 
54 static int DRI2EventBase;
55 
56 
57 static Bool
validDrawable(ClientPtr client,XID drawable,Mask access_mode,DrawablePtr * pDrawable,int * status)58 validDrawable(ClientPtr client, XID drawable, Mask access_mode,
59               DrawablePtr *pDrawable, int *status)
60 {
61     *status = dixLookupDrawable(pDrawable, drawable, client,
62                                 M_DRAWABLE_WINDOW | M_DRAWABLE_PIXMAP,
63                                 access_mode);
64     if (*status != Success) {
65         client->errorValue = drawable;
66         return FALSE;
67     }
68 
69     return TRUE;
70 }
71 
72 static int
ProcDRI2QueryVersion(ClientPtr client)73 ProcDRI2QueryVersion(ClientPtr client)
74 {
75     REQUEST(xDRI2QueryVersionReq);
76     xDRI2QueryVersionReply rep = {
77         .type = X_Reply,
78         .sequenceNumber = client->sequence,
79         .length = 0,
80         .majorVersion = dri2_major,
81         .minorVersion = dri2_minor
82     };
83 
84     if (client->swapped)
85         swaps(&stuff->length);
86 
87     REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
88 
89     if (client->swapped) {
90         swaps(&rep.sequenceNumber);
91         swapl(&rep.length);
92         swapl(&rep.majorVersion);
93         swapl(&rep.minorVersion);
94     }
95 
96     WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep);
97 
98     return Success;
99 }
100 
101 static int
ProcDRI2Connect(ClientPtr client)102 ProcDRI2Connect(ClientPtr client)
103 {
104     REQUEST(xDRI2ConnectReq);
105     xDRI2ConnectReply rep = {
106         .type = X_Reply,
107         .sequenceNumber = client->sequence,
108         .length = 0,
109         .driverNameLength = 0,
110         .deviceNameLength = 0
111     };
112     DrawablePtr pDraw;
113     int fd, status;
114     const char *driverName;
115     const char *deviceName;
116 
117     REQUEST_SIZE_MATCH(xDRI2ConnectReq);
118     if (!validDrawable(client, stuff->window, DixGetAttrAccess,
119                        &pDraw, &status))
120         return status;
121 
122     if (!DRI2Connect(client, pDraw->pScreen,
123                      stuff->driverType, &fd, &driverName, &deviceName))
124         goto fail;
125 
126     rep.driverNameLength = strlen(driverName);
127     rep.deviceNameLength = strlen(deviceName);
128     rep.length = (rep.driverNameLength + 3) / 4 +
129         (rep.deviceNameLength + 3) / 4;
130 
131  fail:
132     WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
133     WriteToClient(client, rep.driverNameLength, driverName);
134     WriteToClient(client, rep.deviceNameLength, deviceName);
135 
136     return Success;
137 }
138 
139 static int
ProcDRI2Authenticate(ClientPtr client)140 ProcDRI2Authenticate(ClientPtr client)
141 {
142     REQUEST(xDRI2AuthenticateReq);
143     xDRI2AuthenticateReply rep;
144     DrawablePtr pDraw;
145     int status;
146 
147     REQUEST_SIZE_MATCH(xDRI2AuthenticateReq);
148     if (!validDrawable(client, stuff->window, DixGetAttrAccess,
149                        &pDraw, &status))
150         return status;
151 
152     rep = (xDRI2AuthenticateReply) {
153         .type = X_Reply,
154         .sequenceNumber = client->sequence,
155         .length = 0,
156         .authenticated = DRI2Authenticate(client, pDraw->pScreen, stuff->magic)
157     };
158     WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);
159 
160     return Success;
161 }
162 
163 static void
DRI2InvalidateBuffersEvent(DrawablePtr pDraw,void * priv,XID id)164 DRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv, XID id)
165 {
166     ClientPtr client = priv;
167     xDRI2InvalidateBuffers event = {
168         .type = DRI2EventBase + DRI2_InvalidateBuffers,
169         .drawable = id
170     };
171 
172     WriteEventsToClient(client, 1, (xEvent *) &event);
173 }
174 
175 static int
ProcDRI2CreateDrawable(ClientPtr client)176 ProcDRI2CreateDrawable(ClientPtr client)
177 {
178     REQUEST(xDRI2CreateDrawableReq);
179     DrawablePtr pDrawable;
180     int status;
181 
182     REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq);
183 
184     if (!validDrawable(client, stuff->drawable, DixAddAccess,
185                        &pDrawable, &status))
186         return status;
187 
188     status = DRI2CreateDrawable(client, pDrawable, stuff->drawable,
189                                 DRI2InvalidateBuffersEvent, client);
190     if (status != Success)
191         return status;
192 
193     return Success;
194 }
195 
196 static int
ProcDRI2DestroyDrawable(ClientPtr client)197 ProcDRI2DestroyDrawable(ClientPtr client)
198 {
199     REQUEST(xDRI2DestroyDrawableReq);
200     DrawablePtr pDrawable;
201     int status;
202 
203     REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq);
204     if (!validDrawable(client, stuff->drawable, DixRemoveAccess,
205                        &pDrawable, &status))
206         return status;
207 
208     return Success;
209 }
210 
211 static int
send_buffers_reply(ClientPtr client,DrawablePtr pDrawable,DRI2BufferPtr * buffers,int count,int width,int height)212 send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
213                    DRI2BufferPtr * buffers, int count, int width, int height)
214 {
215     xDRI2GetBuffersReply rep;
216     int skip = 0;
217     int i;
218 
219     if (buffers == NULL)
220         return BadAlloc;
221 
222     if (pDrawable->type == DRAWABLE_WINDOW) {
223         for (i = 0; i < count; i++) {
224             /* Do not send the real front buffer of a window to the client.
225              */
226             if (buffers[i]->attachment == DRI2BufferFrontLeft) {
227                 skip++;
228                 continue;
229             }
230         }
231     }
232 
233     rep = (xDRI2GetBuffersReply) {
234         .type = X_Reply,
235         .sequenceNumber = client->sequence,
236         .length = (count - skip) * sizeof(xDRI2Buffer) / 4,
237         .width = width,
238         .height = height,
239         .count = count - skip
240     };
241     WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep);
242 
243     for (i = 0; i < count; i++) {
244         xDRI2Buffer buffer;
245 
246         /* Do not send the real front buffer of a window to the client.
247          */
248         if ((pDrawable->type == DRAWABLE_WINDOW)
249             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
250             continue;
251         }
252 
253         buffer.attachment = buffers[i]->attachment;
254         buffer.name = buffers[i]->name;
255         buffer.pitch = buffers[i]->pitch;
256         buffer.cpp = buffers[i]->cpp;
257         buffer.flags = buffers[i]->flags;
258         WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
259     }
260     return Success;
261 }
262 
263 static int
ProcDRI2GetBuffers(ClientPtr client)264 ProcDRI2GetBuffers(ClientPtr client)
265 {
266     REQUEST(xDRI2GetBuffersReq);
267     DrawablePtr pDrawable;
268     DRI2BufferPtr *buffers;
269     int status, width, height, count;
270     unsigned int *attachments;
271 
272     REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq);
273     /* stuff->count is a count of CARD32 attachments that follows */
274     if (stuff->count > (INT_MAX / sizeof(CARD32)))
275         return BadLength;
276     REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * sizeof(CARD32));
277 
278     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
279                        &pDrawable, &status))
280         return status;
281 
282     if (DRI2ThrottleClient(client, pDrawable))
283         return Success;
284 
285     attachments = (unsigned int *) &stuff[1];
286     buffers = DRI2GetBuffers(pDrawable, &width, &height,
287                              attachments, stuff->count, &count);
288 
289     return send_buffers_reply(client, pDrawable, buffers, count, width, height);
290 
291 }
292 
293 static int
ProcDRI2GetBuffersWithFormat(ClientPtr client)294 ProcDRI2GetBuffersWithFormat(ClientPtr client)
295 {
296     REQUEST(xDRI2GetBuffersReq);
297     DrawablePtr pDrawable;
298     DRI2BufferPtr *buffers;
299     int status, width, height, count;
300     unsigned int *attachments;
301 
302     REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq);
303     /* stuff->count is a count of pairs of CARD32s (attachments & formats)
304        that follows */
305     if (stuff->count > (INT_MAX / (2 * sizeof(CARD32))))
306         return BadLength;
307     REQUEST_FIXED_SIZE(xDRI2GetBuffersReq,
308                        stuff->count * (2 * sizeof(CARD32)));
309     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
310                        &pDrawable, &status))
311         return status;
312 
313     if (DRI2ThrottleClient(client, pDrawable))
314         return Success;
315 
316     attachments = (unsigned int *) &stuff[1];
317     buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
318                                        attachments, stuff->count, &count);
319 
320     return send_buffers_reply(client, pDrawable, buffers, count, width, height);
321 }
322 
323 static int
ProcDRI2CopyRegion(ClientPtr client)324 ProcDRI2CopyRegion(ClientPtr client)
325 {
326     REQUEST(xDRI2CopyRegionReq);
327     xDRI2CopyRegionReply rep;
328     DrawablePtr pDrawable;
329     int status;
330     RegionPtr pRegion;
331 
332     REQUEST_SIZE_MATCH(xDRI2CopyRegionReq);
333 
334     if (!validDrawable(client, stuff->drawable, DixWriteAccess,
335                        &pDrawable, &status))
336         return status;
337 
338     VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
339 
340     status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src);
341     if (status != Success)
342         return status;
343 
344     /* CopyRegion needs to be a round trip to make sure the X server
345      * queues the swap buffer rendering commands before the DRI client
346      * continues rendering.  The reply has a bitmask to signal the
347      * presense of optional return values as well, but we're not using
348      * that yet.
349      */
350 
351     rep = (xDRI2CopyRegionReply) {
352         .type = X_Reply,
353         .sequenceNumber = client->sequence,
354         .length = 0
355     };
356 
357     WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep);
358 
359     return Success;
360 }
361 
362 static void
load_swap_reply(xDRI2SwapBuffersReply * rep,CARD64 sbc)363 load_swap_reply(xDRI2SwapBuffersReply * rep, CARD64 sbc)
364 {
365     rep->swap_hi = sbc >> 32;
366     rep->swap_lo = sbc & 0xffffffff;
367 }
368 
369 static CARD64
vals_to_card64(CARD32 lo,CARD32 hi)370 vals_to_card64(CARD32 lo, CARD32 hi)
371 {
372     return (CARD64) hi << 32 | lo;
373 }
374 
375 static void
DRI2SwapEvent(ClientPtr client,void * data,int type,CARD64 ust,CARD64 msc,CARD32 sbc)376 DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
377               CARD32 sbc)
378 {
379     DrawablePtr pDrawable = data;
380     xDRI2BufferSwapComplete2 event = {
381         .type = DRI2EventBase + DRI2_BufferSwapComplete,
382         .event_type = type,
383         .drawable = pDrawable->id,
384         .ust_hi = (CARD64) ust >> 32,
385         .ust_lo = ust & 0xffffffff,
386         .msc_hi = (CARD64) msc >> 32,
387         .msc_lo = msc & 0xffffffff,
388         .sbc = sbc
389     };
390 
391     WriteEventsToClient(client, 1, (xEvent *) &event);
392 }
393 
394 static int
ProcDRI2SwapBuffers(ClientPtr client)395 ProcDRI2SwapBuffers(ClientPtr client)
396 {
397     REQUEST(xDRI2SwapBuffersReq);
398     xDRI2SwapBuffersReply rep = {
399         .type = X_Reply,
400         .sequenceNumber = client->sequence,
401         .length = 0
402     };
403     DrawablePtr pDrawable;
404     CARD64 target_msc, divisor, remainder, swap_target;
405     int status;
406 
407     REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
408 
409     if (!validDrawable(client, stuff->drawable,
410                        DixReadAccess | DixWriteAccess, &pDrawable, &status))
411         return status;
412 
413     /*
414      * Ensures an out of control client can't exhaust our swap queue, and
415      * also orders swaps.
416      */
417     if (DRI2ThrottleClient(client, pDrawable))
418         return Success;
419 
420     target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
421     divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
422     remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
423 
424     status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
425                              &swap_target, DRI2SwapEvent, pDrawable);
426     if (status != Success)
427         return BadDrawable;
428 
429     load_swap_reply(&rep, swap_target);
430 
431     WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
432 
433     return Success;
434 }
435 
436 static void
load_msc_reply(xDRI2MSCReply * rep,CARD64 ust,CARD64 msc,CARD64 sbc)437 load_msc_reply(xDRI2MSCReply * rep, CARD64 ust, CARD64 msc, CARD64 sbc)
438 {
439     rep->ust_hi = ust >> 32;
440     rep->ust_lo = ust & 0xffffffff;
441     rep->msc_hi = msc >> 32;
442     rep->msc_lo = msc & 0xffffffff;
443     rep->sbc_hi = sbc >> 32;
444     rep->sbc_lo = sbc & 0xffffffff;
445 }
446 
447 static int
ProcDRI2GetMSC(ClientPtr client)448 ProcDRI2GetMSC(ClientPtr client)
449 {
450     REQUEST(xDRI2GetMSCReq);
451     xDRI2MSCReply rep = {
452         .type = X_Reply,
453         .sequenceNumber = client->sequence,
454         .length = 0
455     };
456     DrawablePtr pDrawable;
457     CARD64 ust, msc, sbc;
458     int status;
459 
460     REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
461 
462     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
463                        &status))
464         return status;
465 
466     status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
467     if (status != Success)
468         return status;
469 
470     load_msc_reply(&rep, ust, msc, sbc);
471 
472     WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
473 
474     return Success;
475 }
476 
477 static int
ProcDRI2WaitMSC(ClientPtr client)478 ProcDRI2WaitMSC(ClientPtr client)
479 {
480     REQUEST(xDRI2WaitMSCReq);
481     DrawablePtr pDrawable;
482     CARD64 target, divisor, remainder;
483     int status;
484 
485     /* FIXME: in restart case, client may be gone at this point */
486 
487     REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
488 
489     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
490                        &status))
491         return status;
492 
493     target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
494     divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
495     remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
496 
497     status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
498     if (status != Success)
499         return status;
500 
501     return Success;
502 }
503 
504 int
ProcDRI2WaitMSCReply(ClientPtr client,CARD64 ust,CARD64 msc,CARD64 sbc)505 ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
506 {
507     xDRI2MSCReply rep = {
508         .type = X_Reply,
509         .sequenceNumber = client->sequence,
510         .length = 0
511     };
512 
513     load_msc_reply(&rep, ust, msc, sbc);
514 
515     WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
516 
517     return Success;
518 }
519 
520 static int
ProcDRI2SwapInterval(ClientPtr client)521 ProcDRI2SwapInterval(ClientPtr client)
522 {
523     REQUEST(xDRI2SwapIntervalReq);
524     DrawablePtr pDrawable;
525     int status;
526 
527     /* FIXME: in restart case, client may be gone at this point */
528 
529     REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq);
530 
531     if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
532                        &pDrawable, &status))
533         return status;
534 
535     DRI2SwapInterval(pDrawable, stuff->interval);
536 
537     return Success;
538 }
539 
540 static int
ProcDRI2WaitSBC(ClientPtr client)541 ProcDRI2WaitSBC(ClientPtr client)
542 {
543     REQUEST(xDRI2WaitSBCReq);
544     DrawablePtr pDrawable;
545     CARD64 target;
546     int status;
547 
548     REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
549 
550     if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
551                        &status))
552         return status;
553 
554     target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
555     status = DRI2WaitSBC(client, pDrawable, target);
556 
557     return status;
558 }
559 
560 static int
ProcDRI2GetParam(ClientPtr client)561 ProcDRI2GetParam(ClientPtr client)
562 {
563     REQUEST(xDRI2GetParamReq);
564     xDRI2GetParamReply rep = {
565         .type = X_Reply,
566         .sequenceNumber = client->sequence,
567         .length = 0
568     };
569     DrawablePtr pDrawable;
570     CARD64 value;
571     int status;
572 
573     REQUEST_SIZE_MATCH(xDRI2GetParamReq);
574 
575     if (!validDrawable(client, stuff->drawable, DixReadAccess,
576                        &pDrawable, &status))
577         return status;
578 
579     status = DRI2GetParam(client, pDrawable, stuff->param,
580                           &rep.is_param_recognized, &value);
581     rep.value_hi = value >> 32;
582     rep.value_lo = value & 0xffffffff;
583 
584     if (status != Success)
585         return status;
586 
587     WriteToClient(client, sizeof(xDRI2GetParamReply), &rep);
588 
589     return status;
590 }
591 
592 static int
ProcDRI2Dispatch(ClientPtr client)593 ProcDRI2Dispatch(ClientPtr client)
594 {
595     REQUEST(xReq);
596 
597     switch (stuff->data) {
598     case X_DRI2QueryVersion:
599         return ProcDRI2QueryVersion(client);
600     }
601 
602     if (!client->local)
603         return BadRequest;
604 
605     switch (stuff->data) {
606     case X_DRI2Connect:
607         return ProcDRI2Connect(client);
608     case X_DRI2Authenticate:
609         return ProcDRI2Authenticate(client);
610     case X_DRI2CreateDrawable:
611         return ProcDRI2CreateDrawable(client);
612     case X_DRI2DestroyDrawable:
613         return ProcDRI2DestroyDrawable(client);
614     case X_DRI2GetBuffers:
615         return ProcDRI2GetBuffers(client);
616     case X_DRI2CopyRegion:
617         return ProcDRI2CopyRegion(client);
618     case X_DRI2GetBuffersWithFormat:
619         return ProcDRI2GetBuffersWithFormat(client);
620     case X_DRI2SwapBuffers:
621         return ProcDRI2SwapBuffers(client);
622     case X_DRI2GetMSC:
623         return ProcDRI2GetMSC(client);
624     case X_DRI2WaitMSC:
625         return ProcDRI2WaitMSC(client);
626     case X_DRI2WaitSBC:
627         return ProcDRI2WaitSBC(client);
628     case X_DRI2SwapInterval:
629         return ProcDRI2SwapInterval(client);
630     case X_DRI2GetParam:
631         return ProcDRI2GetParam(client);
632     default:
633         return BadRequest;
634     }
635 }
636 
637 static int _X_COLD
SProcDRI2Connect(ClientPtr client)638 SProcDRI2Connect(ClientPtr client)
639 {
640     REQUEST(xDRI2ConnectReq);
641     xDRI2ConnectReply rep = {
642         .type = X_Reply,
643         .sequenceNumber = client->sequence,
644         .length = 0,
645         .driverNameLength = 0,
646         .deviceNameLength = 0
647     };
648 
649     /* If the client is swapped, it's not local.  Talk to the hand. */
650 
651     swaps(&stuff->length);
652     if (sizeof(*stuff) / 4 != client->req_len)
653         return BadLength;
654 
655     swaps(&rep.sequenceNumber);
656 
657     WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
658 
659     return Success;
660 }
661 
662 static int _X_COLD
SProcDRI2Dispatch(ClientPtr client)663 SProcDRI2Dispatch(ClientPtr client)
664 {
665     REQUEST(xReq);
666 
667     /*
668      * Only local clients are allowed DRI access, but remote clients
669      * still need these requests to find out cleanly.
670      */
671     switch (stuff->data) {
672     case X_DRI2QueryVersion:
673         return ProcDRI2QueryVersion(client);
674     case X_DRI2Connect:
675         return SProcDRI2Connect(client);
676     default:
677         return BadRequest;
678     }
679 }
680 
681 void
DRI2ExtensionInit(void)682 DRI2ExtensionInit(void)
683 {
684     ExtensionEntry *dri2Extension;
685 
686 #ifdef PANORAMIX
687     if (!noPanoramiXExtension)
688         return;
689 #endif
690 
691     dri2Extension = AddExtension(DRI2_NAME,
692                                  DRI2NumberEvents,
693                                  DRI2NumberErrors,
694                                  ProcDRI2Dispatch,
695                                  SProcDRI2Dispatch, NULL, StandardMinorOpcode);
696 
697     DRI2EventBase = dri2Extension->eventBase;
698 
699     DRI2ModuleSetup();
700 }
701