Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2008 George Sapountzis
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21.  * SOFTWARE.
  22.  */
  23.  
  24. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  25.  
  26. #include <X11/Xlib.h>
  27. #include "glxclient.h"
  28. #include <dlfcn.h>
  29. #include "dri_common.h"
  30.  
  31. struct drisw_display
  32. {
  33.    __GLXDRIdisplay base;
  34. };
  35.  
  36. struct drisw_context
  37. {
  38.    struct glx_context base;
  39.    __DRIcontext *driContext;
  40.  
  41. };
  42.  
  43. struct drisw_screen
  44. {
  45.    struct glx_screen base;
  46.  
  47.    __DRIscreen *driScreen;
  48.    __GLXDRIscreen vtable;
  49.    const __DRIcoreExtension *core;
  50.    const __DRIswrastExtension *swrast;
  51.    const __DRItexBufferExtension *texBuffer;
  52.  
  53.    const __DRIconfig **driver_configs;
  54.  
  55.    void *driver;
  56. };
  57.  
  58. struct drisw_drawable
  59. {
  60.    __GLXDRIdrawable base;
  61.  
  62.    GC gc;
  63.    GC swapgc;
  64.  
  65.    __DRIdrawable *driDrawable;
  66.    XVisualInfo *visinfo;
  67.    XImage *ximage;
  68. };
  69.  
  70. static Bool
  71. XCreateDrawable(struct drisw_drawable * pdp,
  72.                 Display * dpy, XID drawable, int visualid)
  73. {
  74.    XGCValues gcvalues;
  75.    long visMask;
  76.    XVisualInfo visTemp;
  77.    int num_visuals;
  78.  
  79.    /* create GC's */
  80.    pdp->gc = XCreateGC(dpy, drawable, 0, NULL);
  81.    pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL);
  82.  
  83.    gcvalues.function = GXcopy;
  84.    gcvalues.graphics_exposures = False;
  85.    XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues);
  86.    XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues);
  87.    XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues);
  88.  
  89.    /* visual */
  90.    visTemp.visualid = visualid;
  91.    visMask = VisualIDMask;
  92.    pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals);
  93.  
  94.    if (!pdp->visinfo || num_visuals == 0)
  95.       return False;
  96.  
  97.    /* create XImage */
  98.    pdp->ximage = XCreateImage(dpy,
  99.                               pdp->visinfo->visual,
  100.                               pdp->visinfo->depth,
  101.                               ZPixmap, 0,             /* format, offset */
  102.                               NULL,                   /* data */
  103.                               0, 0,                   /* width, height */
  104.                               32,                     /* bitmap_pad */
  105.                               0);                     /* bytes_per_line */
  106.  
  107.   /**
  108.    * swrast does not handle 24-bit depth with 24 bpp, so let X do the
  109.    * the conversion for us.
  110.    */
  111.   if (pdp->ximage->bits_per_pixel == 24)
  112.      pdp->ximage->bits_per_pixel = 32;
  113.  
  114.    return True;
  115. }
  116.  
  117. static void
  118. XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
  119. {
  120.    XDestroyImage(pdp->ximage);
  121.    free(pdp->visinfo);
  122.  
  123.    XFreeGC(dpy, pdp->gc);
  124.    XFreeGC(dpy, pdp->swapgc);
  125. }
  126.  
  127. /**
  128.  * swrast loader functions
  129.  */
  130.  
  131. static void
  132. swrastGetDrawableInfo(__DRIdrawable * draw,
  133.                       int *x, int *y, int *w, int *h,
  134.                       void *loaderPrivate)
  135. {
  136.    struct drisw_drawable *pdp = loaderPrivate;
  137.    __GLXDRIdrawable *pdraw = &(pdp->base);
  138.    Display *dpy = pdraw->psc->dpy;
  139.    Drawable drawable;
  140.  
  141.    Window root;
  142.    unsigned uw, uh, bw, depth;
  143.  
  144.    drawable = pdraw->xDrawable;
  145.  
  146.    XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
  147.    *w = uw;
  148.    *h = uh;
  149. }
  150.  
  151. /**
  152.  * Align renderbuffer pitch.
  153.  *
  154.  * This should be chosen by the driver and the loader (libGL, xserver/glx)
  155.  * should use the driver provided pitch.
  156.  *
  157.  * It seems that the xorg loader (that is the xserver loading swrast_dri for
  158.  * indirect rendering, not client-side libGL) requires that the pitch is
  159.  * exactly the image width padded to 32 bits. XXX
  160.  *
  161.  * The above restriction can probably be overcome by using ScratchPixmap and
  162.  * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
  163.  * the scratch pixmap to 'pitch / cpp'.
  164.  */
  165. static inline int
  166. bytes_per_line(unsigned pitch_bits, unsigned mul)
  167. {
  168.    unsigned mask = mul - 1;
  169.  
  170.    return ((pitch_bits + mask) & ~mask) / 8;
  171. }
  172.  
  173. static void
  174. swrastPutImage(__DRIdrawable * draw, int op,
  175.                int x, int y, int w, int h,
  176.                char *data, void *loaderPrivate)
  177. {
  178.    struct drisw_drawable *pdp = loaderPrivate;
  179.    __GLXDRIdrawable *pdraw = &(pdp->base);
  180.    Display *dpy = pdraw->psc->dpy;
  181.    Drawable drawable;
  182.    XImage *ximage;
  183.    GC gc;
  184.  
  185.    switch (op) {
  186.    case __DRI_SWRAST_IMAGE_OP_DRAW:
  187.       gc = pdp->gc;
  188.       break;
  189.    case __DRI_SWRAST_IMAGE_OP_SWAP:
  190.       gc = pdp->swapgc;
  191.       break;
  192.    default:
  193.       return;
  194.    }
  195.  
  196.    drawable = pdraw->xDrawable;
  197.  
  198.    ximage = pdp->ximage;
  199.    ximage->data = data;
  200.    ximage->width = w;
  201.    ximage->height = h;
  202.    ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
  203.  
  204.    XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
  205.  
  206.    ximage->data = NULL;
  207. }
  208.  
  209. static void
  210. swrastGetImage(__DRIdrawable * read,
  211.                int x, int y, int w, int h,
  212.                char *data, void *loaderPrivate)
  213. {
  214.    struct drisw_drawable *prp = loaderPrivate;
  215.    __GLXDRIdrawable *pread = &(prp->base);
  216.    Display *dpy = pread->psc->dpy;
  217.    Drawable readable;
  218.    XImage *ximage;
  219.  
  220.    readable = pread->xDrawable;
  221.  
  222.    ximage = prp->ximage;
  223.    ximage->data = data;
  224.    ximage->width = w;
  225.    ximage->height = h;
  226.    ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
  227.  
  228.    XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
  229.  
  230.    ximage->data = NULL;
  231. }
  232.  
  233. static const __DRIswrastLoaderExtension swrastLoaderExtension = {
  234.    {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
  235.    swrastGetDrawableInfo,
  236.    swrastPutImage,
  237.    swrastGetImage
  238. };
  239.  
  240. static const __DRIextension *loader_extensions[] = {
  241.    &systemTimeExtension.base,
  242.    &swrastLoaderExtension.base,
  243.    NULL
  244. };
  245.  
  246. /**
  247.  * GLXDRI functions
  248.  */
  249.  
  250. static void
  251. drisw_destroy_context(struct glx_context *context)
  252. {
  253.    struct drisw_context *pcp = (struct drisw_context *) context;
  254.    struct drisw_screen *psc = (struct drisw_screen *) context->psc;
  255.  
  256.    driReleaseDrawables(&pcp->base);
  257.  
  258.    free((char *) context->extensions);
  259.  
  260.    (*psc->core->destroyContext) (pcp->driContext);
  261.  
  262.    free(pcp);
  263. }
  264.  
  265. static int
  266. drisw_bind_context(struct glx_context *context, struct glx_context *old,
  267.                    GLXDrawable draw, GLXDrawable read)
  268. {
  269.    struct drisw_context *pcp = (struct drisw_context *) context;
  270.    struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
  271.    struct drisw_drawable *pdraw, *pread;
  272.  
  273.    pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
  274.    pread = (struct drisw_drawable *) driFetchDrawable(context, read);
  275.  
  276.    driReleaseDrawables(&pcp->base);
  277.  
  278.    if (pdraw == NULL || pread == NULL)
  279.       return GLXBadDrawable;
  280.  
  281.    if ((*psc->core->bindContext) (pcp->driContext,
  282.                                   pdraw->driDrawable, pread->driDrawable))
  283.       return Success;
  284.  
  285.    return GLXBadContext;
  286. }
  287.  
  288. static void
  289. drisw_unbind_context(struct glx_context *context, struct glx_context *new)
  290. {
  291.    struct drisw_context *pcp = (struct drisw_context *) context;
  292.    struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
  293.  
  294.    (*psc->core->unbindContext) (pcp->driContext);
  295. }
  296.  
  297. static void
  298. drisw_bind_tex_image(Display * dpy,
  299.                     GLXDrawable drawable,
  300.                     int buffer, const int *attrib_list)
  301. {
  302.    struct glx_context *gc = __glXGetCurrentContext();
  303.    struct drisw_context *pcp = (struct drisw_context *) gc;
  304.    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
  305.    struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
  306.    struct drisw_screen *psc;
  307.  
  308.    __glXInitialize(dpy);
  309.  
  310.    if (pdraw != NULL) {
  311.       psc = (struct drisw_screen *) base->psc;
  312.  
  313.       if (!psc->texBuffer)
  314.          return;
  315.  
  316.       if (psc->texBuffer->base.version >= 2 &&
  317.         psc->texBuffer->setTexBuffer2 != NULL) {
  318.               (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
  319.                                            pdraw->base.textureTarget,
  320.                                            pdraw->base.textureFormat,
  321.                                            pdraw->driDrawable);
  322.       }
  323.       else {
  324.               (*psc->texBuffer->setTexBuffer) (pcp->driContext,
  325.                                           pdraw->base.textureTarget,
  326.                                           pdraw->driDrawable);
  327.       }
  328.    }
  329. }
  330.  
  331. static void
  332. drisw_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
  333. {
  334. #if __DRI_TEX_BUFFER_VERSION >= 3
  335.    struct glx_context *gc = __glXGetCurrentContext();
  336.    struct dri2_context *pcp = (struct dri2_context *) gc;
  337.    __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
  338.    struct glx_display *dpyPriv = __glXInitialize(dpy);
  339.    struct dri2_drawable *pdraw = (struct dri2_drawable *) base;
  340.    struct dri2_screen *psc;
  341.  
  342.    if (pdraw != NULL) {
  343.       psc = (struct dri2_screen *) base->psc;
  344.  
  345.       if (!psc->texBuffer)
  346.          return;
  347.  
  348.       if (psc->texBuffer->base.version >= 3 &&
  349.           psc->texBuffer->releaseTexBuffer != NULL) {
  350.          (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
  351.                                            pdraw->base.textureTarget,
  352.                                            pdraw->driDrawable);
  353.       }
  354.    }
  355. #endif
  356. }
  357.  
  358. static const struct glx_context_vtable drisw_context_vtable = {
  359.    drisw_destroy_context,
  360.    drisw_bind_context,
  361.    drisw_unbind_context,
  362.    NULL,
  363.    NULL,
  364.    DRI_glXUseXFont,
  365.    drisw_bind_tex_image,
  366.    drisw_release_tex_image,
  367.    NULL, /* get_proc_address */
  368. };
  369.  
  370. static struct glx_context *
  371. drisw_create_context(struct glx_screen *base,
  372.                      struct glx_config *config_base,
  373.                      struct glx_context *shareList, int renderType)
  374. {
  375.    struct drisw_context *pcp, *pcp_shared;
  376.    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
  377.    struct drisw_screen *psc = (struct drisw_screen *) base;
  378.    __DRIcontext *shared = NULL;
  379.  
  380.    if (!psc->base.driScreen)
  381.       return NULL;
  382.  
  383.    /* Check the renderType value */
  384.    if (!validate_renderType_against_config(config_base, renderType))
  385.        return NULL;
  386.  
  387.    if (shareList) {
  388.       /* If the shareList context is not a DRISW context, we cannot possibly
  389.        * create a DRISW context that shares it.
  390.        */
  391.       if (shareList->vtable->destroy != drisw_destroy_context) {
  392.          return NULL;
  393.       }
  394.  
  395.       pcp_shared = (struct drisw_context *) shareList;
  396.       shared = pcp_shared->driContext;
  397.    }
  398.  
  399.    pcp = calloc(1, sizeof *pcp);
  400.    if (pcp == NULL)
  401.       return NULL;
  402.  
  403.    if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
  404.       free(pcp);
  405.       return NULL;
  406.    }
  407.  
  408.    pcp->base.renderType = renderType;
  409.  
  410.    pcp->driContext =
  411.       (*psc->core->createNewContext) (psc->driScreen,
  412.                                       config->driConfig, shared, pcp);
  413.    if (pcp->driContext == NULL) {
  414.       free(pcp);
  415.       return NULL;
  416.    }
  417.  
  418.    pcp->base.vtable = &drisw_context_vtable;
  419.  
  420.    return &pcp->base;
  421. }
  422.  
  423. static struct glx_context *
  424. drisw_create_context_attribs(struct glx_screen *base,
  425.                              struct glx_config *config_base,
  426.                              struct glx_context *shareList,
  427.                              unsigned num_attribs,
  428.                              const uint32_t *attribs,
  429.                              unsigned *error)
  430. {
  431.    struct drisw_context *pcp, *pcp_shared;
  432.    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
  433.    struct drisw_screen *psc = (struct drisw_screen *) base;
  434.    __DRIcontext *shared = NULL;
  435.  
  436.    uint32_t minor_ver;
  437.    uint32_t major_ver;
  438.    uint32_t renderType;
  439.    uint32_t flags;
  440.    unsigned api;
  441.    int reset;
  442.    uint32_t ctx_attribs[2 * 4];
  443.    unsigned num_ctx_attribs = 0;
  444.  
  445.    if (!psc->base.driScreen)
  446.       return NULL;
  447.  
  448.    if (psc->swrast->base.version < 3)
  449.       return NULL;
  450.  
  451.    /* Remap the GLX tokens to DRI2 tokens.
  452.     */
  453.    if (!dri2_convert_glx_attribs(num_attribs, attribs,
  454.                                  &major_ver, &minor_ver, &renderType, &flags,
  455.                                  &api, &reset, error))
  456.       return NULL;
  457.  
  458.    /* Check the renderType value */
  459.    if (!validate_renderType_against_config(config_base, renderType)) {
  460.        return NULL;
  461.    }
  462.  
  463.    if (reset != __DRI_CTX_RESET_NO_NOTIFICATION)
  464.       return NULL;
  465.  
  466.    if (shareList) {
  467.       pcp_shared = (struct drisw_context *) shareList;
  468.       shared = pcp_shared->driContext;
  469.    }
  470.  
  471.    pcp = calloc(1, sizeof *pcp);
  472.    if (pcp == NULL)
  473.       return NULL;
  474.  
  475.    if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
  476.       free(pcp);
  477.       return NULL;
  478.    }
  479.  
  480.    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
  481.    ctx_attribs[num_ctx_attribs++] = major_ver;
  482.    ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
  483.    ctx_attribs[num_ctx_attribs++] = minor_ver;
  484.  
  485.    if (flags != 0) {
  486.       ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
  487.  
  488.       /* The current __DRI_CTX_FLAG_* values are identical to the
  489.        * GLX_CONTEXT_*_BIT values.
  490.        */
  491.       ctx_attribs[num_ctx_attribs++] = flags;
  492.    }
  493.  
  494.    pcp->base.renderType = renderType;
  495.  
  496.    pcp->driContext =
  497.       (*psc->swrast->createContextAttribs) (psc->driScreen,
  498.                                             api,
  499.                                             config->driConfig,
  500.                                             shared,
  501.                                             num_ctx_attribs / 2,
  502.                                             ctx_attribs,
  503.                                             error,
  504.                                             pcp);
  505.    if (pcp->driContext == NULL) {
  506.       free(pcp);
  507.       return NULL;
  508.    }
  509.  
  510.    pcp->base.vtable = &drisw_context_vtable;
  511.  
  512.    return &pcp->base;
  513. }
  514.  
  515. static void
  516. driswDestroyDrawable(__GLXDRIdrawable * pdraw)
  517. {
  518.    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
  519.    struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
  520.  
  521.    (*psc->core->destroyDrawable) (pdp->driDrawable);
  522.  
  523.    XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
  524.    free(pdp);
  525. }
  526.  
  527. static __GLXDRIdrawable *
  528. driswCreateDrawable(struct glx_screen *base, XID xDrawable,
  529.                     GLXDrawable drawable, struct glx_config *modes)
  530. {
  531.    struct drisw_drawable *pdp;
  532.    __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
  533.    struct drisw_screen *psc = (struct drisw_screen *) base;
  534.    Bool ret;
  535.    const __DRIswrastExtension *swrast = psc->swrast;
  536.  
  537.    pdp = calloc(1, sizeof(*pdp));
  538.    if (!pdp)
  539.       return NULL;
  540.  
  541.    pdp->base.xDrawable = xDrawable;
  542.    pdp->base.drawable = drawable;
  543.    pdp->base.psc = &psc->base;
  544.  
  545.    ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
  546.    if (!ret) {
  547.       free(pdp);
  548.       return NULL;
  549.    }
  550.  
  551.    /* Create a new drawable */
  552.    pdp->driDrawable =
  553.       (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp);
  554.  
  555.    if (!pdp->driDrawable) {
  556.       XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
  557.       free(pdp);
  558.       return NULL;
  559.    }
  560.  
  561.    pdp->base.destroyDrawable = driswDestroyDrawable;
  562.  
  563.    return &pdp->base;
  564. }
  565.  
  566. static int64_t
  567. driswSwapBuffers(__GLXDRIdrawable * pdraw,
  568.                  int64_t target_msc, int64_t divisor, int64_t remainder,
  569.                  Bool flush)
  570. {
  571.    struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
  572.    struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
  573.  
  574.    (void) target_msc;
  575.    (void) divisor;
  576.    (void) remainder;
  577.  
  578.    if (flush) {
  579.       glFlush();
  580.    }
  581.  
  582.    (*psc->core->swapBuffers) (pdp->driDrawable);
  583.  
  584.    return 0;
  585. }
  586.  
  587. static void
  588. driswDestroyScreen(struct glx_screen *base)
  589. {
  590.    struct drisw_screen *psc = (struct drisw_screen *) base;
  591.  
  592.    /* Free the direct rendering per screen data */
  593.    (*psc->core->destroyScreen) (psc->driScreen);
  594.    driDestroyConfigs(psc->driver_configs);
  595.    psc->driScreen = NULL;
  596.    if (psc->driver)
  597.       dlclose(psc->driver);
  598. }
  599.  
  600. #define SWRAST_DRIVER_NAME "swrast"
  601.  
  602. static void *
  603. driOpenSwrast(void)
  604. {
  605.    void *driver = NULL;
  606.  
  607.    if (driver == NULL)
  608.       driver = driOpenDriver(SWRAST_DRIVER_NAME);
  609.  
  610.    return driver;
  611. }
  612.  
  613. static const struct glx_screen_vtable drisw_screen_vtable = {
  614.    drisw_create_context,
  615.    drisw_create_context_attribs
  616. };
  617.  
  618. static void
  619. driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
  620. {
  621.    int i;
  622.  
  623.    __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
  624.  
  625.    if (psc->swrast->base.version >= 3) {
  626.       __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
  627.       __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
  628.  
  629.       /* DRISW version >= 2 implies support for OpenGL ES 2.0.
  630.        */
  631.       __glXEnableDirectExtension(&psc->base,
  632.                                  "GLX_EXT_create_context_es2_profile");
  633.    }
  634.  
  635.    /* FIXME: Figure out what other extensions can be ported here from dri2. */
  636.    for (i = 0; extensions[i]; i++) {
  637.       if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
  638.          psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
  639.          __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
  640.       }
  641.    }
  642. }
  643.  
  644. static struct glx_screen *
  645. driswCreateScreen(int screen, struct glx_display *priv)
  646. {
  647.    __GLXDRIscreen *psp;
  648.    const __DRIconfig **driver_configs;
  649.    const __DRIextension **extensions;
  650.    struct drisw_screen *psc;
  651.    struct glx_config *configs = NULL, *visuals = NULL;
  652.    int i;
  653.  
  654.    psc = calloc(1, sizeof *psc);
  655.    if (psc == NULL)
  656.       return NULL;
  657.  
  658.    if (!glx_screen_init(&psc->base, screen, priv)) {
  659.       free(psc);
  660.       return NULL;
  661.    }
  662.  
  663.    psc->driver = driOpenSwrast();
  664.    if (psc->driver == NULL)
  665.       goto handle_error;
  666.  
  667.    extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
  668.    if (extensions == NULL) {
  669.       ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
  670.       goto handle_error;
  671.    }
  672.  
  673.    for (i = 0; extensions[i]; i++) {
  674.       if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
  675.          psc->core = (__DRIcoreExtension *) extensions[i];
  676.       if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
  677.          psc->swrast = (__DRIswrastExtension *) extensions[i];
  678.    }
  679.  
  680.    if (psc->core == NULL || psc->swrast == NULL) {
  681.       ErrorMessageF("core dri extension not found\n");
  682.       goto handle_error;
  683.    }
  684.  
  685.    psc->driScreen =
  686.       psc->swrast->createNewScreen(screen, loader_extensions,
  687.                                    &driver_configs, psc);
  688.    if (psc->driScreen == NULL) {
  689.       ErrorMessageF("failed to create dri screen\n");
  690.       goto handle_error;
  691.    }
  692.  
  693.    extensions = psc->core->getExtensions(psc->driScreen);
  694.    driswBindExtensions(psc, extensions);
  695.  
  696.    configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
  697.    visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
  698.  
  699.    if (!configs || !visuals)
  700.        goto handle_error;
  701.  
  702.    glx_config_destroy_list(psc->base.configs);
  703.    psc->base.configs = configs;
  704.    glx_config_destroy_list(psc->base.visuals);
  705.    psc->base.visuals = visuals;
  706.  
  707.    psc->driver_configs = driver_configs;
  708.  
  709.    psc->base.vtable = &drisw_screen_vtable;
  710.    psp = &psc->vtable;
  711.    psc->base.driScreen = psp;
  712.    psp->destroyScreen = driswDestroyScreen;
  713.    psp->createDrawable = driswCreateDrawable;
  714.    psp->swapBuffers = driswSwapBuffers;
  715.  
  716.    return &psc->base;
  717.  
  718.  handle_error:
  719.    if (configs)
  720.        glx_config_destroy_list(configs);
  721.    if (visuals)
  722.        glx_config_destroy_list(visuals);
  723.    if (psc->driScreen)
  724.        psc->core->destroyScreen(psc->driScreen);
  725.    psc->driScreen = NULL;
  726.  
  727.    if (psc->driver)
  728.       dlclose(psc->driver);
  729.    glx_screen_cleanup(&psc->base);
  730.    free(psc);
  731.  
  732.    CriticalErrorMessageF("failed to load driver: %s\n", SWRAST_DRIVER_NAME);
  733.  
  734.    return NULL;
  735. }
  736.  
  737. /* Called from __glXFreeDisplayPrivate.
  738.  */
  739. static void
  740. driswDestroyDisplay(__GLXDRIdisplay * dpy)
  741. {
  742.    free(dpy);
  743. }
  744.  
  745. /*
  746.  * Allocate, initialize and return a __DRIdisplayPrivate object.
  747.  * This is called from __glXInitialize() when we are given a new
  748.  * display pointer.
  749.  */
  750. _X_HIDDEN __GLXDRIdisplay *
  751. driswCreateDisplay(Display * dpy)
  752. {
  753.    struct drisw_display *pdpyp;
  754.  
  755.    pdpyp = malloc(sizeof *pdpyp);
  756.    if (pdpyp == NULL)
  757.       return NULL;
  758.  
  759.    pdpyp->base.destroyDisplay = driswDestroyDisplay;
  760.    pdpyp->base.createScreen = driswCreateScreen;
  761.  
  762.    return &pdpyp->base;
  763. }
  764.  
  765. #endif /* GLX_DIRECT_RENDERING */
  766.