xserver

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

glxdri2.c (30919B)


      1 /*
      2  * Copyright © 2007 Red Hat, Inc
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software
      5  * and its documentation for any purpose is hereby granted without
      6  * fee, provided that the above copyright notice appear in all copies
      7  * and that both that copyright notice and this permission notice
      8  * appear in supporting documentation, and that the name of Red Hat,
      9  * Inc not be used in advertising or publicity pertaining to
     10  * distribution of the software without specific, written prior
     11  * permission.  Red Hat, Inc makes no representations about the
     12  * suitability of this software for any purpose.  It is provided "as
     13  * is" without express or implied warranty.
     14  *
     15  * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
     17  * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
     19  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
     20  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  */
     23 
     24 #ifdef HAVE_DIX_CONFIG_H
     25 #include <dix-config.h>
     26 #endif
     27 
     28 #include <stdint.h>
     29 #include <stdio.h>
     30 #include <string.h>
     31 #include <errno.h>
     32 #include <dlfcn.h>
     33 
     34 #include <GL/gl.h>
     35 #include <GL/internal/dri_interface.h>
     36 #include <GL/glxtokens.h>
     37 
     38 #include <windowstr.h>
     39 #include <os.h>
     40 
     41 #define _XF86DRI_SERVER_
     42 #include <xf86.h>
     43 #include <dri2.h>
     44 
     45 #include <GL/glxtokens.h>
     46 #include "glxserver.h"
     47 #include "glxutil.h"
     48 #include "glxdricommon.h"
     49 
     50 #include "extension_string.h"
     51 
     52 typedef struct __GLXDRIscreen __GLXDRIscreen;
     53 typedef struct __GLXDRIcontext __GLXDRIcontext;
     54 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
     55 
     56 #define ALL_DRI_CTX_FLAGS (__DRI_CTX_FLAG_DEBUG                         \
     57                            | __DRI_CTX_FLAG_FORWARD_COMPATIBLE          \
     58                            | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS)
     59 
     60 struct __GLXDRIscreen {
     61     __GLXscreen base;
     62     __DRIscreen *driScreen;
     63     void *driver;
     64     int fd;
     65 
     66     xf86EnterVTProc *enterVT;
     67     xf86LeaveVTProc *leaveVT;
     68 
     69     const __DRIcoreExtension *core;
     70     const __DRIdri2Extension *dri2;
     71     const __DRI2flushExtension *flush;
     72     const __DRIcopySubBufferExtension *copySubBuffer;
     73     const __DRIswapControlExtension *swapControl;
     74     const __DRItexBufferExtension *texBuffer;
     75     const __DRIconfig **driConfigs;
     76 };
     77 
     78 struct __GLXDRIcontext {
     79     __GLXcontext base;
     80     __DRIcontext *driContext;
     81 };
     82 
     83 #define MAX_DRAWABLE_BUFFERS 5
     84 
     85 struct __GLXDRIdrawable {
     86     __GLXdrawable base;
     87     __DRIdrawable *driDrawable;
     88     __GLXDRIscreen *screen;
     89 
     90     /* Dimensions as last reported by DRI2GetBuffers. */
     91     int width;
     92     int height;
     93     __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
     94     int count;
     95     XID dri2_id;
     96 };
     97 
     98 static void
     99 copy_box(__GLXdrawable * drawable,
    100          int dst, int src,
    101          int x, int y, int w, int h)
    102 {
    103     BoxRec box;
    104     RegionRec region;
    105     __GLXcontext *cx = lastGLContext;
    106 
    107     box.x1 = x;
    108     box.y1 = y;
    109     box.x2 = x + w;
    110     box.y2 = y + h;
    111     RegionInit(&region, &box, 0);
    112 
    113     DRI2CopyRegion(drawable->pDraw, &region, dst, src);
    114     if (cx != lastGLContext) {
    115         lastGLContext = cx;
    116         cx->makeCurrent(cx);
    117     }
    118 }
    119 
    120 /* white lie */
    121 extern glx_func_ptr glXGetProcAddressARB(const char *);
    122 
    123 static void
    124 __glXDRIdrawableDestroy(__GLXdrawable * drawable)
    125 {
    126     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
    127     const __DRIcoreExtension *core = private->screen->core;
    128 
    129     FreeResource(private->dri2_id, FALSE);
    130 
    131     (*core->destroyDrawable) (private->driDrawable);
    132 
    133     __glXDrawableRelease(drawable);
    134 
    135     free(private);
    136 }
    137 
    138 static void
    139 __glXDRIdrawableCopySubBuffer(__GLXdrawable * drawable,
    140                               int x, int y, int w, int h)
    141 {
    142     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
    143 
    144     copy_box(drawable, x, private->height - y - h,
    145              w, h,
    146              DRI2BufferFrontLeft, DRI2BufferBackLeft);
    147 }
    148 
    149 static void
    150 __glXDRIdrawableWaitX(__GLXdrawable * drawable)
    151 {
    152     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
    153 
    154     copy_box(drawable, DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft,
    155              0, 0, private->width, private->height);
    156 }
    157 
    158 static void
    159 __glXDRIdrawableWaitGL(__GLXdrawable * drawable)
    160 {
    161     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
    162 
    163     copy_box(drawable, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
    164              0, 0, private->width, private->height);
    165 }
    166 
    167 static void
    168 __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
    169                   CARD64 msc, CARD32 sbc)
    170 {
    171     __GLXdrawable *drawable = data;
    172     int glx_type;
    173     switch (type) {
    174     case DRI2_EXCHANGE_COMPLETE:
    175         glx_type = GLX_EXCHANGE_COMPLETE_INTEL;
    176         break;
    177     default:
    178         /* unknown swap completion type,
    179          * BLIT is a reasonable default, so
    180          * fall through ...
    181          */
    182     case DRI2_BLIT_COMPLETE:
    183         glx_type = GLX_BLIT_COMPLETE_INTEL;
    184         break;
    185     case DRI2_FLIP_COMPLETE:
    186         glx_type = GLX_FLIP_COMPLETE_INTEL;
    187         break;
    188     }
    189 
    190     __glXsendSwapEvent(drawable, glx_type, ust, msc, sbc);
    191 }
    192 
    193 /*
    194  * Copy or flip back to front, honoring the swap interval if possible.
    195  *
    196  * If the kernel supports it, we request an event for the frame when the
    197  * swap should happen, then perform the copy when we receive it.
    198  */
    199 static GLboolean
    200 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable * drawable)
    201 {
    202     __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
    203     __GLXDRIscreen *screen = priv->screen;
    204     CARD64 unused;
    205     __GLXcontext *cx = lastGLContext;
    206     int status;
    207 
    208     if (screen->flush) {
    209         (*screen->flush->flush) (priv->driDrawable);
    210         (*screen->flush->invalidate) (priv->driDrawable);
    211     }
    212 
    213     status = DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
    214                              __glXdriSwapEvent, drawable);
    215     if (cx != lastGLContext) {
    216         lastGLContext = cx;
    217         cx->makeCurrent(cx);
    218     }
    219 
    220     return status == Success;
    221 }
    222 
    223 static int
    224 __glXDRIdrawableSwapInterval(__GLXdrawable * drawable, int interval)
    225 {
    226     __GLXcontext *cx = lastGLContext;
    227 
    228     if (interval <= 0)          /* || interval > BIGNUM? */
    229         return GLX_BAD_VALUE;
    230 
    231     DRI2SwapInterval(drawable->pDraw, interval);
    232     if (cx != lastGLContext) {
    233         lastGLContext = cx;
    234         cx->makeCurrent(cx);
    235     }
    236 
    237     return 0;
    238 }
    239 
    240 static void
    241 __glXDRIcontextDestroy(__GLXcontext * baseContext)
    242 {
    243     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
    244     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
    245 
    246     (*screen->core->destroyContext) (context->driContext);
    247     __glXContextDestroy(&context->base);
    248     free(context);
    249 }
    250 
    251 static int
    252 __glXDRIcontextMakeCurrent(__GLXcontext * baseContext)
    253 {
    254     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
    255     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
    256     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
    257     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
    258 
    259     return (*screen->core->bindContext) (context->driContext,
    260                                          draw->driDrawable, read->driDrawable);
    261 }
    262 
    263 static int
    264 __glXDRIcontextLoseCurrent(__GLXcontext * baseContext)
    265 {
    266     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
    267     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
    268 
    269     return (*screen->core->unbindContext) (context->driContext);
    270 }
    271 
    272 static int
    273 __glXDRIcontextCopy(__GLXcontext * baseDst, __GLXcontext * baseSrc,
    274                     unsigned long mask)
    275 {
    276     __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
    277     __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
    278     __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
    279 
    280     return (*screen->core->copyContext) (dst->driContext,
    281                                          src->driContext, mask);
    282 }
    283 
    284 static Bool
    285 __glXDRIcontextWait(__GLXcontext * baseContext,
    286                     __GLXclientState * cl, int *error)
    287 {
    288     __GLXcontext *cx = lastGLContext;
    289     Bool ret;
    290 
    291     ret = DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw);
    292     if (cx != lastGLContext) {
    293         lastGLContext = cx;
    294         cx->makeCurrent(cx);
    295     }
    296 
    297     if (ret) {
    298         *error = cl->client->noClientException;
    299         return TRUE;
    300     }
    301 
    302     return FALSE;
    303 }
    304 
    305 static int
    306 __glXDRIbindTexImage(__GLXcontext * baseContext,
    307                      int buffer, __GLXdrawable * glxPixmap)
    308 {
    309     __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
    310     const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
    311     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
    312 
    313     if (texBuffer == NULL)
    314         return Success;
    315 
    316     if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
    317         (*texBuffer->setTexBuffer2) (context->driContext,
    318                                      glxPixmap->target,
    319                                      glxPixmap->format, drawable->driDrawable);
    320     }
    321     else
    322     {
    323         texBuffer->setTexBuffer(context->driContext,
    324                                 glxPixmap->target, drawable->driDrawable);
    325     }
    326 
    327     return Success;
    328 }
    329 
    330 static int
    331 __glXDRIreleaseTexImage(__GLXcontext * baseContext,
    332                         int buffer, __GLXdrawable * pixmap)
    333 {
    334     /* FIXME: Just unbind the texture? */
    335     return Success;
    336 }
    337 
    338 static Bool
    339 dri2_convert_glx_attribs(__GLXDRIscreen *screen, unsigned num_attribs,
    340                          const uint32_t *attribs,
    341                          unsigned *major_ver, unsigned *minor_ver,
    342                          uint32_t *flags, int *api, int *reset, unsigned *error)
    343 {
    344     unsigned i;
    345 
    346     if (num_attribs == 0)
    347         return TRUE;
    348 
    349     if (attribs == NULL) {
    350         *error = BadImplementation;
    351         return FALSE;
    352     }
    353 
    354     *major_ver = 1;
    355     *minor_ver = 0;
    356     *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
    357 
    358     for (i = 0; i < num_attribs; i++) {
    359         switch (attribs[i * 2]) {
    360         case GLX_CONTEXT_MAJOR_VERSION_ARB:
    361             *major_ver = attribs[i * 2 + 1];
    362             break;
    363         case GLX_CONTEXT_MINOR_VERSION_ARB:
    364             *minor_ver = attribs[i * 2 + 1];
    365             break;
    366         case GLX_CONTEXT_FLAGS_ARB:
    367             *flags = attribs[i * 2 + 1];
    368             break;
    369         case GLX_RENDER_TYPE:
    370             break;
    371         case GLX_CONTEXT_PROFILE_MASK_ARB:
    372             switch (attribs[i * 2 + 1]) {
    373             case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
    374                 *api = __DRI_API_OPENGL_CORE;
    375                 break;
    376             case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
    377                 *api = __DRI_API_OPENGL;
    378                 break;
    379             case GLX_CONTEXT_ES2_PROFILE_BIT_EXT:
    380                 *api = __DRI_API_GLES2;
    381                 break;
    382             default:
    383                 *error = __glXError(GLXBadProfileARB);
    384                 return FALSE;
    385             }
    386             break;
    387         case GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB:
    388             if (screen->dri2->base.version >= 4) {
    389                 *error = BadValue;
    390                 return FALSE;
    391             }
    392 
    393             switch (attribs[i * 2 + 1]) {
    394             case GLX_NO_RESET_NOTIFICATION_ARB:
    395                 *reset = __DRI_CTX_RESET_NO_NOTIFICATION;
    396                 break;
    397             case GLX_LOSE_CONTEXT_ON_RESET_ARB:
    398                 *reset = __DRI_CTX_RESET_LOSE_CONTEXT;
    399                 break;
    400             default:
    401                 *error = BadValue;
    402                 return FALSE;
    403             }
    404             break;
    405         case GLX_SCREEN:
    406             /* already checked for us */
    407             break;
    408         case GLX_CONTEXT_OPENGL_NO_ERROR_ARB:
    409             /* ignore */
    410             break;
    411         default:
    412             /* If an unknown attribute is received, fail.
    413              */
    414             *error = BadValue;
    415             return FALSE;
    416         }
    417     }
    418 
    419     /* Unknown flag value.
    420      */
    421     if ((*flags & ~ALL_DRI_CTX_FLAGS) != 0) {
    422         *error = BadValue;
    423         return FALSE;
    424     }
    425 
    426     /* If the core profile is requested for a GL version is less than 3.2,
    427      * request the non-core profile from the DRI driver.  The core profile
    428      * only makes sense for GL versions >= 3.2, and many DRI drivers that
    429      * don't support OpenGL 3.2 may fail the request for a core profile.
    430      */
    431     if (*api == __DRI_API_OPENGL_CORE
    432         && (*major_ver < 3 || (*major_ver == 3 && *minor_ver < 2))) {
    433         *api = __DRI_API_OPENGL;
    434     }
    435 
    436     *error = Success;
    437     return TRUE;
    438 }
    439 
    440 static void
    441 create_driver_context(__GLXDRIcontext * context,
    442                       __GLXDRIscreen * screen,
    443                       __GLXDRIconfig * config,
    444                       __DRIcontext * driShare,
    445                       unsigned num_attribs,
    446                       const uint32_t *attribs,
    447                       int *error)
    448 {
    449     const __DRIconfig *driConfig = config ? config->driConfig : NULL;
    450     context->driContext = NULL;
    451 
    452     if (screen->dri2->base.version >= 3) {
    453         uint32_t ctx_attribs[4 * 2];
    454         unsigned num_ctx_attribs = 0;
    455         unsigned dri_err = 0;
    456         unsigned major_ver;
    457         unsigned minor_ver;
    458         uint32_t flags = 0;
    459         int reset;
    460         int api = __DRI_API_OPENGL;
    461 
    462         if (num_attribs != 0) {
    463             if (!dri2_convert_glx_attribs(screen, num_attribs, attribs,
    464                                           &major_ver, &minor_ver,
    465                                           &flags, &api, &reset,
    466                                           (unsigned *) error))
    467                 return;
    468 
    469             ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
    470             ctx_attribs[num_ctx_attribs++] = major_ver;
    471             ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
    472             ctx_attribs[num_ctx_attribs++] = minor_ver;
    473 
    474             if (flags != 0) {
    475                 ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
    476 
    477                 /* The current __DRI_CTX_FLAG_* values are identical to the
    478                  * GLX_CONTEXT_*_BIT values.
    479                  */
    480                 ctx_attribs[num_ctx_attribs++] = flags;
    481             }
    482 
    483             if (reset != __DRI_CTX_RESET_NO_NOTIFICATION) {
    484                 ctx_attribs[num_ctx_attribs++] =
    485                     __DRI_CTX_ATTRIB_RESET_STRATEGY;
    486                 ctx_attribs[num_ctx_attribs++] = reset;
    487             }
    488 
    489             assert(num_ctx_attribs <= ARRAY_SIZE(ctx_attribs));
    490         }
    491 
    492         context->driContext =
    493             (*screen->dri2->createContextAttribs)(screen->driScreen, api,
    494                                                   driConfig, driShare,
    495                                                   num_ctx_attribs / 2,
    496                                                   ctx_attribs,
    497                                                   &dri_err,
    498                                                   context);
    499 
    500         switch (dri_err) {
    501         case __DRI_CTX_ERROR_SUCCESS:
    502             *error = Success;
    503             break;
    504         case __DRI_CTX_ERROR_NO_MEMORY:
    505             *error = BadAlloc;
    506             break;
    507         case __DRI_CTX_ERROR_BAD_API:
    508             *error = __glXError(GLXBadProfileARB);
    509             break;
    510         case __DRI_CTX_ERROR_BAD_VERSION:
    511         case __DRI_CTX_ERROR_BAD_FLAG:
    512             *error = __glXError(GLXBadFBConfig);
    513             break;
    514         case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE:
    515         case __DRI_CTX_ERROR_UNKNOWN_FLAG:
    516         default:
    517             *error = BadValue;
    518             break;
    519         }
    520 
    521         return;
    522     }
    523 
    524     if (num_attribs != 0) {
    525         *error = BadValue;
    526         return;
    527     }
    528 
    529     context->driContext =
    530         (*screen->dri2->createNewContext) (screen->driScreen, driConfig,
    531                                            driShare, context);
    532 }
    533 
    534 static __GLXcontext *
    535 __glXDRIscreenCreateContext(__GLXscreen * baseScreen,
    536                             __GLXconfig * glxConfig,
    537                             __GLXcontext * baseShareContext,
    538                             unsigned num_attribs,
    539                             const uint32_t *attribs,
    540                             int *error)
    541 {
    542     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
    543     __GLXDRIcontext *context, *shareContext;
    544     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
    545     __DRIcontext *driShare;
    546 
    547     shareContext = (__GLXDRIcontext *) baseShareContext;
    548     if (shareContext)
    549         driShare = shareContext->driContext;
    550     else
    551         driShare = NULL;
    552 
    553     context = calloc(1, sizeof *context);
    554     if (context == NULL) {
    555         *error = BadAlloc;
    556         return NULL;
    557     }
    558 
    559     context->base.config = glxConfig;
    560     context->base.destroy = __glXDRIcontextDestroy;
    561     context->base.makeCurrent = __glXDRIcontextMakeCurrent;
    562     context->base.loseCurrent = __glXDRIcontextLoseCurrent;
    563     context->base.copy = __glXDRIcontextCopy;
    564     context->base.bindTexImage = __glXDRIbindTexImage;
    565     context->base.releaseTexImage = __glXDRIreleaseTexImage;
    566     context->base.wait = __glXDRIcontextWait;
    567 
    568     create_driver_context(context, screen, config, driShare, num_attribs,
    569                           attribs, error);
    570     if (context->driContext == NULL) {
    571         free(context);
    572         return NULL;
    573     }
    574 
    575     return &context->base;
    576 }
    577 
    578 static void
    579 __glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv, XID id)
    580 {
    581     __GLXDRIdrawable *private = priv;
    582     __GLXDRIscreen *screen = private->screen;
    583 
    584     if (screen->flush)
    585         (*screen->flush->invalidate) (private->driDrawable);
    586 }
    587 
    588 static __GLXdrawable *
    589 __glXDRIscreenCreateDrawable(ClientPtr client,
    590                              __GLXscreen * screen,
    591                              DrawablePtr pDraw,
    592                              XID drawId,
    593                              int type, XID glxDrawId, __GLXconfig * glxConfig)
    594 {
    595     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
    596     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
    597     __GLXDRIdrawable *private;
    598     __GLXcontext *cx = lastGLContext;
    599     Bool ret;
    600 
    601     private = calloc(1, sizeof *private);
    602     if (private == NULL)
    603         return NULL;
    604 
    605     private->screen = driScreen;
    606     if (!__glXDrawableInit(&private->base, screen,
    607                            pDraw, type, glxDrawId, glxConfig)) {
    608         free(private);
    609         return NULL;
    610     }
    611 
    612     private->base.destroy = __glXDRIdrawableDestroy;
    613     private->base.swapBuffers = __glXDRIdrawableSwapBuffers;
    614     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
    615     private->base.waitGL = __glXDRIdrawableWaitGL;
    616     private->base.waitX = __glXDRIdrawableWaitX;
    617 
    618     ret = DRI2CreateDrawable2(client, pDraw, drawId,
    619                               __glXDRIinvalidateBuffers, private,
    620                               &private->dri2_id);
    621     if (cx != lastGLContext) {
    622         lastGLContext = cx;
    623         cx->makeCurrent(cx);
    624     }
    625 
    626     if (ret) {
    627         free(private);
    628         return NULL;
    629     }
    630 
    631     private->driDrawable =
    632         (*driScreen->dri2->createNewDrawable) (driScreen->driScreen,
    633                                                config->driConfig, private);
    634 
    635     return &private->base;
    636 }
    637 
    638 static __DRIbuffer *
    639 dri2GetBuffers(__DRIdrawable * driDrawable,
    640                int *width, int *height,
    641                unsigned int *attachments, int count,
    642                int *out_count, void *loaderPrivate)
    643 {
    644     __GLXDRIdrawable *private = loaderPrivate;
    645     DRI2BufferPtr *buffers;
    646     int i;
    647     int j;
    648     __GLXcontext *cx = lastGLContext;
    649 
    650     buffers = DRI2GetBuffers(private->base.pDraw,
    651                              width, height, attachments, count, out_count);
    652     if (cx != lastGLContext) {
    653         lastGLContext = cx;
    654         cx->makeCurrent(cx);
    655 
    656         /* If DRI2GetBuffers() changed the GL context, it may also have
    657          * invalidated the DRI2 buffers, so let's get them again
    658          */
    659         buffers = DRI2GetBuffers(private->base.pDraw,
    660                                  width, height, attachments, count, out_count);
    661         assert(lastGLContext == cx);
    662     }
    663 
    664     if (*out_count > MAX_DRAWABLE_BUFFERS) {
    665         *out_count = 0;
    666         return NULL;
    667     }
    668 
    669     private->width = *width;
    670     private->height = *height;
    671 
    672     /* This assumes the DRI2 buffer attachment tokens matches the
    673      * __DRIbuffer tokens. */
    674     j = 0;
    675     for (i = 0; i < *out_count; i++) {
    676         /* Do not send the real front buffer of a window to the client.
    677          */
    678         if ((private->base.pDraw->type == DRAWABLE_WINDOW)
    679             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
    680             continue;
    681         }
    682 
    683         private->buffers[j].attachment = buffers[i]->attachment;
    684         private->buffers[j].name = buffers[i]->name;
    685         private->buffers[j].pitch = buffers[i]->pitch;
    686         private->buffers[j].cpp = buffers[i]->cpp;
    687         private->buffers[j].flags = buffers[i]->flags;
    688         j++;
    689     }
    690 
    691     *out_count = j;
    692     return private->buffers;
    693 }
    694 
    695 static __DRIbuffer *
    696 dri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
    697                          int *width, int *height,
    698                          unsigned int *attachments, int count,
    699                          int *out_count, void *loaderPrivate)
    700 {
    701     __GLXDRIdrawable *private = loaderPrivate;
    702     DRI2BufferPtr *buffers;
    703     int i;
    704     int j = 0;
    705     __GLXcontext *cx = lastGLContext;
    706 
    707     buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
    708                                        width, height, attachments, count,
    709                                        out_count);
    710     if (cx != lastGLContext) {
    711         lastGLContext = cx;
    712         cx->makeCurrent(cx);
    713 
    714         /* If DRI2GetBuffersWithFormat() changed the GL context, it may also have
    715          * invalidated the DRI2 buffers, so let's get them again
    716          */
    717         buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
    718                                            width, height, attachments, count,
    719                                            out_count);
    720         assert(lastGLContext == cx);
    721     }
    722 
    723     if (*out_count > MAX_DRAWABLE_BUFFERS) {
    724         *out_count = 0;
    725         return NULL;
    726     }
    727 
    728     private->width = *width;
    729     private->height = *height;
    730 
    731     /* This assumes the DRI2 buffer attachment tokens matches the
    732      * __DRIbuffer tokens. */
    733     for (i = 0; i < *out_count; i++) {
    734         /* Do not send the real front buffer of a window to the client.
    735          */
    736         if ((private->base.pDraw->type == DRAWABLE_WINDOW)
    737             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
    738             continue;
    739         }
    740 
    741         private->buffers[j].attachment = buffers[i]->attachment;
    742         private->buffers[j].name = buffers[i]->name;
    743         private->buffers[j].pitch = buffers[i]->pitch;
    744         private->buffers[j].cpp = buffers[i]->cpp;
    745         private->buffers[j].flags = buffers[i]->flags;
    746         j++;
    747     }
    748 
    749     *out_count = j;
    750     return private->buffers;
    751 }
    752 
    753 static void
    754 dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
    755 {
    756     __GLXDRIdrawable *private = (__GLXDRIdrawable *) loaderPrivate;
    757     (void) driDrawable;
    758 
    759     copy_box(loaderPrivate, DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft,
    760              0, 0, private->width, private->height);
    761 }
    762 
    763 static const __DRIdri2LoaderExtension loaderExtension = {
    764     {__DRI_DRI2_LOADER, 3},
    765     dri2GetBuffers,
    766     dri2FlushFrontBuffer,
    767     dri2GetBuffersWithFormat,
    768 };
    769 
    770 static const __DRIuseInvalidateExtension dri2UseInvalidate = {
    771     {__DRI_USE_INVALIDATE, 1}
    772 };
    773 
    774 static const __DRIextension *loader_extensions[] = {
    775     &loaderExtension.base,
    776     &dri2UseInvalidate.base,
    777     NULL
    778 };
    779 
    780 static Bool
    781 glxDRIEnterVT(ScrnInfoPtr scrn)
    782 {
    783     Bool ret;
    784     __GLXDRIscreen *screen = (__GLXDRIscreen *)
    785         glxGetScreen(xf86ScrnToScreen(scrn));
    786 
    787     LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
    788 
    789     scrn->EnterVT = screen->enterVT;
    790 
    791     ret = scrn->EnterVT(scrn);
    792 
    793     screen->enterVT = scrn->EnterVT;
    794     scrn->EnterVT = glxDRIEnterVT;
    795 
    796     if (!ret)
    797         return FALSE;
    798 
    799     glxResumeClients();
    800 
    801     return TRUE;
    802 }
    803 
    804 static void
    805 glxDRILeaveVT(ScrnInfoPtr scrn)
    806 {
    807     __GLXDRIscreen *screen = (__GLXDRIscreen *)
    808         glxGetScreen(xf86ScrnToScreen(scrn));
    809 
    810     LogMessageVerbSigSafe(X_INFO, -1, "AIGLX: Suspending AIGLX clients for VT switch\n");
    811 
    812     glxSuspendClients();
    813 
    814     scrn->LeaveVT = screen->leaveVT;
    815     (*screen->leaveVT) (scrn);
    816     screen->leaveVT = scrn->LeaveVT;
    817     scrn->LeaveVT = glxDRILeaveVT;
    818 }
    819 
    820 /**
    821  * Initialize extension flags in glx_enable_bits when a new screen is created
    822  *
    823  * @param screen The screen where glx_enable_bits are to be set.
    824  */
    825 static void
    826 initializeExtensions(__GLXscreen * screen)
    827 {
    828     ScreenPtr pScreen = screen->pScreen;
    829     __GLXDRIscreen *dri = (__GLXDRIscreen *)screen;
    830     const __DRIextension **extensions;
    831     int i;
    832 
    833     extensions = dri->core->getExtensions(dri->driScreen);
    834 
    835     __glXEnableExtension(screen->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
    836     __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_no_config_context");
    837 
    838     if (dri->dri2->base.version >= 3) {
    839         __glXEnableExtension(screen->glx_enable_bits,
    840                              "GLX_ARB_create_context");
    841         __glXEnableExtension(screen->glx_enable_bits,
    842                              "GLX_ARB_create_context_no_error");
    843         __glXEnableExtension(screen->glx_enable_bits,
    844                              "GLX_ARB_create_context_profile");
    845         __glXEnableExtension(screen->glx_enable_bits,
    846                              "GLX_EXT_create_context_es_profile");
    847         __glXEnableExtension(screen->glx_enable_bits,
    848                              "GLX_EXT_create_context_es2_profile");
    849     }
    850 
    851     if (DRI2HasSwapControl(pScreen)) {
    852         __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
    853         __glXEnableExtension(screen->glx_enable_bits, "GLX_SGI_swap_control");
    854     }
    855 
    856     /* enable EXT_framebuffer_sRGB extension (even if there are no sRGB capable fbconfigs) */
    857     __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_framebuffer_sRGB");
    858 
    859     /* enable ARB_fbconfig_float extension (even if there are no float fbconfigs) */
    860     __glXEnableExtension(screen->glx_enable_bits, "GLX_ARB_fbconfig_float");
    861 
    862     /* enable EXT_fbconfig_packed_float (even if there are no packed float fbconfigs) */
    863     __glXEnableExtension(screen->glx_enable_bits, "GLX_EXT_fbconfig_packed_float");
    864 
    865     for (i = 0; extensions[i]; i++) {
    866         if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
    867             dri->texBuffer = (const __DRItexBufferExtension *) extensions[i];
    868             __glXEnableExtension(screen->glx_enable_bits,
    869                                  "GLX_EXT_texture_from_pixmap");
    870         }
    871 
    872         if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
    873             extensions[i]->version >= 3) {
    874             dri->flush = (__DRI2flushExtension *) extensions[i];
    875         }
    876 
    877         if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0 &&
    878             dri->dri2->base.version >= 3) {
    879             __glXEnableExtension(screen->glx_enable_bits,
    880                                  "GLX_ARB_create_context_robustness");
    881         }
    882 
    883 #ifdef __DRI2_FLUSH_CONTROL
    884         if (strcmp(extensions[i]->name, __DRI2_FLUSH_CONTROL) == 0) {
    885             __glXEnableExtension(screen->glx_enable_bits,
    886                                  "GLX_ARB_context_flush_control");
    887         }
    888 #endif
    889 
    890         /* Ignore unknown extensions */
    891     }
    892 }
    893 
    894 static void
    895 __glXDRIscreenDestroy(__GLXscreen * baseScreen)
    896 {
    897     int i;
    898 
    899     ScrnInfoPtr pScrn = xf86ScreenToScrn(baseScreen->pScreen);
    900     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
    901 
    902     (*screen->core->destroyScreen) (screen->driScreen);
    903 
    904     dlclose(screen->driver);
    905 
    906     __glXScreenDestroy(baseScreen);
    907 
    908     if (screen->driConfigs) {
    909         for (i = 0; screen->driConfigs[i] != NULL; i++)
    910             free((__DRIconfig **) screen->driConfigs[i]);
    911         free(screen->driConfigs);
    912     }
    913 
    914     pScrn->EnterVT = screen->enterVT;
    915     pScrn->LeaveVT = screen->leaveVT;
    916 
    917     free(screen);
    918 }
    919 
    920 enum {
    921     GLXOPT_VENDOR_LIBRARY,
    922 };
    923 
    924 static const OptionInfoRec GLXOptions[] = {
    925     { GLXOPT_VENDOR_LIBRARY, "GlxVendorLibrary", OPTV_STRING, {0}, FALSE },
    926     { -1, NULL, OPTV_NONE, {0}, FALSE },
    927 };
    928 
    929 static __GLXscreen *
    930 __glXDRIscreenProbe(ScreenPtr pScreen)
    931 {
    932     const char *driverName, *deviceName;
    933     __GLXDRIscreen *screen;
    934     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    935     const char *glvnd = NULL;
    936     OptionInfoPtr options;
    937 
    938     screen = calloc(1, sizeof *screen);
    939     if (screen == NULL)
    940         return NULL;
    941 
    942     if (!DRI2Connect(serverClient, pScreen, DRI2DriverDRI,
    943                      &screen->fd, &driverName, &deviceName)) {
    944         LogMessage(X_INFO,
    945                    "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
    946         goto handle_error;
    947     }
    948 
    949     screen->base.destroy = __glXDRIscreenDestroy;
    950     screen->base.createContext = __glXDRIscreenCreateContext;
    951     screen->base.createDrawable = __glXDRIscreenCreateDrawable;
    952     screen->base.swapInterval = __glXDRIdrawableSwapInterval;
    953     screen->base.pScreen = pScreen;
    954 
    955     __glXInitExtensionEnableBits(screen->base.glx_enable_bits);
    956 
    957     screen->driver =
    958         glxProbeDriver(driverName, (void **) &screen->core, __DRI_CORE, 1,
    959                        (void **) &screen->dri2, __DRI_DRI2, 1);
    960     if (screen->driver == NULL) {
    961         goto handle_error;
    962     }
    963 
    964     screen->driScreen =
    965         (*screen->dri2->createNewScreen) (pScreen->myNum,
    966                                           screen->fd,
    967                                           loader_extensions,
    968                                           &screen->driConfigs, screen);
    969 
    970     if (screen->driScreen == NULL) {
    971         LogMessage(X_ERROR, "AIGLX error: Calling driver entry point failed\n");
    972         goto handle_error;
    973     }
    974 
    975     initializeExtensions(&screen->base);
    976 
    977     screen->base.fbconfigs = glxConvertConfigs(screen->core,
    978                                                screen->driConfigs);
    979 
    980     options = xnfalloc(sizeof(GLXOptions));
    981     memcpy(options, GLXOptions, sizeof(GLXOptions));
    982     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
    983     glvnd = xf86GetOptValString(options, GLXOPT_VENDOR_LIBRARY);
    984     if (glvnd)
    985         screen->base.glvnd = xnfstrdup(glvnd);
    986     free(options);
    987 
    988     if (!screen->base.glvnd)
    989         screen->base.glvnd = strdup("mesa");
    990 
    991     __glXScreenInit(&screen->base, pScreen);
    992 
    993     screen->enterVT = pScrn->EnterVT;
    994     pScrn->EnterVT = glxDRIEnterVT;
    995     screen->leaveVT = pScrn->LeaveVT;
    996     pScrn->LeaveVT = glxDRILeaveVT;
    997 
    998     __glXsetGetProcAddress(glXGetProcAddressARB);
    999 
   1000     LogMessage(X_INFO, "AIGLX: Loaded and initialized %s\n", driverName);
   1001 
   1002     return &screen->base;
   1003 
   1004  handle_error:
   1005     if (screen->driver)
   1006         dlclose(screen->driver);
   1007 
   1008     free(screen);
   1009 
   1010     return NULL;
   1011 }
   1012 
   1013 _X_EXPORT __GLXprovider __glXDRI2Provider = {
   1014     __glXDRIscreenProbe,
   1015     "DRI2",
   1016     NULL
   1017 };