"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/glx/glxdri2.c" (29 Mar 2020, 30919 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glxdri2.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    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 };