Subversion Repositories Kolibri OS

Rev

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