xserver

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

dri2ext.c (19081B)


      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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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      * presence 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
    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
    370 vals_to_card64(CARD32 lo, CARD32 hi)
    371 {
    372     return (CARD64) hi << 32 | lo;
    373 }
    374 
    375 static void
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 }