Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * (C) Copyright IBM Corporation 2004
  3.  * All Rights Reserved.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * on the rights to use, copy, modify, merge, publish, distribute, sub
  9.  * license, and/or sell copies of the Software, and to permit persons to whom
  10.  * the Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
  19.  * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. /**
  26.  * \file glx_pbuffer.c
  27.  * Implementation of pbuffer related functions.
  28.  *
  29.  * \author Ian Romanick <idr@us.ibm.com>
  30.  */
  31.  
  32. #include <inttypes.h>
  33. #include "glxclient.h"
  34. #include <X11/extensions/extutil.h>
  35. #include <X11/extensions/Xext.h>
  36. #include <assert.h>
  37. #include <string.h>
  38. #include "glxextensions.h"
  39.  
  40. #ifdef GLX_USE_APPLEGL
  41. #include <pthread.h>
  42. #include "apple_glx_drawable.h"
  43. #endif
  44.  
  45. #include "glx_error.h"
  46.  
  47. #define WARN_ONCE_GLX_1_3(a, b) {               \
  48.                 static int warned=1;            \
  49.                 if(warned) {                    \
  50.                         warn_GLX_1_3((a), b );  \
  51.                         warned=0;               \
  52.                 }                               \
  53.         }
  54.  
  55. /**
  56.  * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems.
  57.  */
  58. static void
  59. warn_GLX_1_3(Display * dpy, const char *function_name)
  60. {
  61.    struct glx_display *priv = __glXInitialize(dpy);
  62.  
  63.    if (priv->minorVersion < 3) {
  64.       fprintf(stderr,
  65.               "WARNING: Application calling GLX 1.3 function \"%s\" "
  66.               "when GLX 1.3 is not supported!  This is an application bug!\n",
  67.               function_name);
  68.    }
  69. }
  70.  
  71. #ifndef GLX_USE_APPLEGL
  72. /**
  73.  * Change a drawable's attribute.
  74.  *
  75.  * This function is used to implement \c glXSelectEvent and
  76.  * \c glXSelectEventSGIX.
  77.  *
  78.  * \note
  79.  * This function dynamically determines whether to use the SGIX_pbuffer
  80.  * version of the protocol or the GLX 1.3 version of the protocol.
  81.  */
  82. static void
  83. ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable,
  84.                         const CARD32 * attribs, size_t num_attribs)
  85. {
  86.    struct glx_display *priv = __glXInitialize(dpy);
  87. #ifdef GLX_DIRECT_RENDERING
  88.    __GLXDRIdrawable *pdraw;
  89. #endif
  90.    CARD32 *output;
  91.    CARD8 opcode;
  92.    int i;
  93.  
  94.    if ((dpy == NULL) || (drawable == 0)) {
  95.       return;
  96.    }
  97.  
  98.    opcode = __glXSetupForCommand(dpy);
  99.    if (!opcode)
  100.       return;
  101.  
  102.    LockDisplay(dpy);
  103.  
  104.    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  105.       xGLXChangeDrawableAttributesReq *req;
  106.  
  107.       GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req);
  108.       output = (CARD32 *) (req + 1);
  109.  
  110.       req->reqType = opcode;
  111.       req->glxCode = X_GLXChangeDrawableAttributes;
  112.       req->drawable = drawable;
  113.       req->numAttribs = (CARD32) num_attribs;
  114.    }
  115.    else {
  116.       xGLXVendorPrivateWithReplyReq *vpreq;
  117.  
  118.       GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq);
  119.       output = (CARD32 *) (vpreq + 1);
  120.  
  121.       vpreq->reqType = opcode;
  122.       vpreq->glxCode = X_GLXVendorPrivateWithReply;
  123.       vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX;
  124.  
  125.       output[0] = (CARD32) drawable;
  126.       output[1] = num_attribs;
  127.       output += 2;
  128.    }
  129.  
  130.    (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs);
  131.  
  132.    UnlockDisplay(dpy);
  133.    SyncHandle();
  134.  
  135. #ifdef GLX_DIRECT_RENDERING
  136.    pdraw = GetGLXDRIDrawable(dpy, drawable);
  137.  
  138.    if (!pdraw)
  139.       return;
  140.  
  141.    for (i = 0; i < num_attribs; i++) {
  142.       switch(attribs[i * 2]) {
  143.       case GLX_EVENT_MASK:
  144.          /* Keep a local copy for masking out DRI2 proto events as needed */
  145.          pdraw->eventMask = attribs[i * 2 + 1];
  146.          break;
  147.       }
  148.    }
  149. #endif
  150.  
  151.    return;
  152. }
  153.  
  154.  
  155. #ifdef GLX_DIRECT_RENDERING
  156. static GLenum
  157. determineTextureTarget(const int *attribs, int numAttribs)
  158. {
  159.    GLenum target = 0;
  160.    int i;
  161.  
  162.    for (i = 0; i < numAttribs; i++) {
  163.       if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
  164.          switch (attribs[2 * i + 1]) {
  165.          case GLX_TEXTURE_2D_EXT:
  166.             target = GL_TEXTURE_2D;
  167.             break;
  168.          case GLX_TEXTURE_RECTANGLE_EXT:
  169.             target = GL_TEXTURE_RECTANGLE_ARB;
  170.             break;
  171.          }
  172.       }
  173.    }
  174.  
  175.    return target;
  176. }
  177.  
  178. static GLenum
  179. determineTextureFormat(const int *attribs, int numAttribs)
  180. {
  181.    int i;
  182.  
  183.    for (i = 0; i < numAttribs; i++) {
  184.       if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
  185.          return attribs[2 * i + 1];
  186.    }
  187.  
  188.    return 0;
  189. }
  190.  
  191. static GLboolean
  192. CreateDRIDrawable(Display *dpy, struct glx_config *config,
  193.                   XID drawable, XID glxdrawable,
  194.                   const int *attrib_list, size_t num_attribs)
  195. {
  196.    struct glx_display *const priv = __glXInitialize(dpy);
  197.    __GLXDRIdrawable *pdraw;
  198.    struct glx_screen *psc;
  199.  
  200.    psc = priv->screens[config->screen];
  201.    if (psc->driScreen == NULL)
  202.       return GL_TRUE;
  203.  
  204.    pdraw = psc->driScreen->createDrawable(psc, drawable,
  205.                                           glxdrawable, config);
  206.    if (pdraw == NULL) {
  207.       fprintf(stderr, "failed to create drawable\n");
  208.       return GL_FALSE;
  209.    }
  210.  
  211.    if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) {
  212.       (*pdraw->destroyDrawable) (pdraw);
  213.       return GL_FALSE;
  214.    }
  215.  
  216.    pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs);
  217.    pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs);
  218.  
  219.    return GL_TRUE;
  220. }
  221.  
  222. static void
  223. DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
  224. {
  225.    struct glx_display *const priv = __glXInitialize(dpy);
  226.    __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
  227.    XID xid;
  228.  
  229.    if (pdraw != NULL) {
  230.       xid = pdraw->xDrawable;
  231.       (*pdraw->destroyDrawable) (pdraw);
  232.       __glxHashDelete(priv->drawHash, drawable);
  233.       if (destroy_xdrawable)
  234.          XFreePixmap(priv->dpy, xid);
  235.    }
  236. }
  237.  
  238. #else
  239.  
  240. static GLboolean
  241. CreateDRIDrawable(Display *dpy, const struct glx_config * fbconfig,
  242.                   XID drawable, XID glxdrawable,
  243.                   const int *attrib_list, size_t num_attribs)
  244. {
  245.     return GL_TRUE;
  246. }
  247.  
  248. static void
  249. DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
  250. {
  251. }
  252.  
  253. #endif
  254.  
  255. /**
  256.  * Get a drawable's attribute.
  257.  *
  258.  * This function is used to implement \c glXGetSelectedEvent and
  259.  * \c glXGetSelectedEventSGIX.
  260.  *
  261.  * \note
  262.  * This function dynamically determines whether to use the SGIX_pbuffer
  263.  * version of the protocol or the GLX 1.3 version of the protocol.
  264.  *
  265.  * \todo
  266.  * The number of attributes returned is likely to be small, probably less than
  267.  * 10.  Given that, this routine should try to use an array on the stack to
  268.  * capture the reply rather than always calling Xmalloc.
  269.  */
  270. static int
  271. GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
  272.                      int attribute, unsigned int *value)
  273. {
  274.    struct glx_display *priv;
  275.    xGLXGetDrawableAttributesReply reply;
  276.    CARD32 *data;
  277.    CARD8 opcode;
  278.    unsigned int length;
  279.    unsigned int i;
  280.    unsigned int num_attributes;
  281.    GLboolean use_glx_1_3;
  282.  
  283.    if (dpy == NULL)
  284.       return 0;
  285.  
  286.    /* Page 38 (page 52 of the PDF) of glxencode1.3.pdf says:
  287.     *
  288.     *     "If drawable is not a valid GLX drawable, a GLXBadDrawable error is
  289.     *     generated."
  290.     */
  291.    if (drawable == 0) {
  292.       __glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false);
  293.       return 0;
  294.    }
  295.  
  296.    priv = __glXInitialize(dpy);
  297.    use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
  298.  
  299.    *value = 0;
  300.  
  301.  
  302.    opcode = __glXSetupForCommand(dpy);
  303.    if (!opcode)
  304.       return 0;
  305.  
  306.    LockDisplay(dpy);
  307.  
  308.    if (use_glx_1_3) {
  309.       xGLXGetDrawableAttributesReq *req;
  310.  
  311.       GetReq(GLXGetDrawableAttributes, req);
  312.       req->reqType = opcode;
  313.       req->glxCode = X_GLXGetDrawableAttributes;
  314.       req->drawable = drawable;
  315.    }
  316.    else {
  317.       xGLXVendorPrivateWithReplyReq *vpreq;
  318.  
  319.       GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  320.       data = (CARD32 *) (vpreq + 1);
  321.       data[0] = (CARD32) drawable;
  322.  
  323.       vpreq->reqType = opcode;
  324.       vpreq->glxCode = X_GLXVendorPrivateWithReply;
  325.       vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
  326.    }
  327.  
  328.    _XReply(dpy, (xReply *) & reply, 0, False);
  329.  
  330.    if (reply.type == X_Error) {
  331.       UnlockDisplay(dpy);
  332.       SyncHandle();
  333.       return 0;
  334.    }
  335.  
  336.    length = reply.length;
  337.    if (length) {
  338.       num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
  339.       data = malloc(length * sizeof(CARD32));
  340.       if (data == NULL) {
  341.          /* Throw data on the floor */
  342.          _XEatData(dpy, length);
  343.       }
  344.       else {
  345.          _XRead(dpy, (char *) data, length * sizeof(CARD32));
  346.  
  347.          /* Search the set of returned attributes for the attribute requested by
  348.           * the caller.
  349.           */
  350.          for (i = 0; i < num_attributes; i++) {
  351.             if (data[i * 2] == attribute) {
  352.                *value = data[(i * 2) + 1];
  353.                break;
  354.             }
  355.          }
  356.  
  357. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  358.          {
  359.             __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
  360.  
  361.             if (pdraw != NULL && !pdraw->textureTarget)
  362.                pdraw->textureTarget =
  363.                   determineTextureTarget((const int *) data, num_attributes);
  364.             if (pdraw != NULL && !pdraw->textureFormat)
  365.                pdraw->textureFormat =
  366.                   determineTextureFormat((const int *) data, num_attributes);
  367.          }
  368. #endif
  369.  
  370.          free(data);
  371.       }
  372.    }
  373.  
  374.    UnlockDisplay(dpy);
  375.    SyncHandle();
  376.  
  377.    return 0;
  378. }
  379.  
  380. static void
  381. protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
  382. {
  383.    xGLXDestroyPbufferReq *req;
  384.    CARD8 opcode;
  385.  
  386.    opcode = __glXSetupForCommand(dpy);
  387.    if (!opcode)
  388.       return;
  389.  
  390.    LockDisplay(dpy);
  391.  
  392.    GetReq(GLXDestroyPbuffer, req);
  393.    req->reqType = opcode;
  394.    req->glxCode = glxCode;
  395.    req->pbuffer = (GLXPbuffer) drawable;
  396.  
  397.    UnlockDisplay(dpy);
  398.    SyncHandle();
  399. }
  400.  
  401. /**
  402.  * Create a non-pbuffer GLX drawable.
  403.  */
  404. static GLXDrawable
  405. CreateDrawable(Display *dpy, struct glx_config *config,
  406.                Drawable drawable, const int *attrib_list, CARD8 glxCode)
  407. {
  408.    xGLXCreateWindowReq *req;
  409.    struct glx_drawable *glxDraw;
  410.    CARD32 *data;
  411.    unsigned int i;
  412.    CARD8 opcode;
  413.    GLXDrawable xid;
  414.  
  415.    i = 0;
  416.    if (attrib_list) {
  417.       while (attrib_list[i * 2] != None)
  418.          i++;
  419.    }
  420.  
  421.    opcode = __glXSetupForCommand(dpy);
  422.    if (!opcode)
  423.       return None;
  424.  
  425.    glxDraw = malloc(sizeof(*glxDraw));
  426.    if (!glxDraw)
  427.       return None;
  428.  
  429.    LockDisplay(dpy);
  430.    GetReqExtra(GLXCreateWindow, 8 * i, req);
  431.    data = (CARD32 *) (req + 1);
  432.  
  433.    req->reqType = opcode;
  434.    req->glxCode = glxCode;
  435.    req->screen = config->screen;
  436.    req->fbconfig = config->fbconfigID;
  437.    req->window = drawable;
  438.    req->glxwindow = xid = XAllocID(dpy);
  439.    req->numAttribs = i;
  440.  
  441.    if (attrib_list)
  442.       memcpy(data, attrib_list, 8 * i);
  443.  
  444.    UnlockDisplay(dpy);
  445.    SyncHandle();
  446.  
  447.    if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) {
  448.       free(glxDraw);
  449.       return None;
  450.    }
  451.  
  452.    if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
  453.       if (glxCode == X_GLXCreatePixmap)
  454.          glxCode = X_GLXDestroyPixmap;
  455.       else
  456.          glxCode = X_GLXDestroyWindow;
  457.       protocolDestroyDrawable(dpy, xid, glxCode);
  458.       xid = None;
  459.    }
  460.  
  461.    return xid;
  462. }
  463.  
  464.  
  465. /**
  466.  * Destroy a non-pbuffer GLX drawable.
  467.  */
  468. static void
  469. DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
  470. {
  471.    if ((dpy == NULL) || (drawable == 0)) {
  472.       return;
  473.    }
  474.  
  475.    protocolDestroyDrawable(dpy, drawable, glxCode);
  476.  
  477.    DestroyGLXDrawable(dpy, drawable);
  478.    DestroyDRIDrawable(dpy, drawable, GL_FALSE);
  479.  
  480.    return;
  481. }
  482.  
  483.  
  484. /**
  485.  * Create a pbuffer.
  486.  *
  487.  * This function is used to implement \c glXCreatePbuffer and
  488.  * \c glXCreateGLXPbufferSGIX.
  489.  *
  490.  * \note
  491.  * This function dynamically determines whether to use the SGIX_pbuffer
  492.  * version of the protocol or the GLX 1.3 version of the protocol.
  493.  */
  494. static GLXDrawable
  495. CreatePbuffer(Display * dpy, struct glx_config *config,
  496.               unsigned int width, unsigned int height,
  497.               const int *attrib_list, GLboolean size_in_attribs)
  498. {
  499.    struct glx_display *priv = __glXInitialize(dpy);
  500.    GLXDrawable id = 0;
  501.    CARD32 *data;
  502.    CARD8 opcode;
  503.    unsigned int i;
  504.    Pixmap pixmap;
  505.    GLboolean glx_1_3 = GL_FALSE;
  506.  
  507.    i = 0;
  508.    if (attrib_list) {
  509.       while (attrib_list[i * 2])
  510.          i++;
  511.    }
  512.  
  513.    opcode = __glXSetupForCommand(dpy);
  514.    if (!opcode)
  515.       return None;
  516.  
  517.    LockDisplay(dpy);
  518.    id = XAllocID(dpy);
  519.  
  520.    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  521.       xGLXCreatePbufferReq *req;
  522.       unsigned int extra = (size_in_attribs) ? 0 : 2;
  523.  
  524.       glx_1_3 = GL_TRUE;
  525.  
  526.       GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
  527.       data = (CARD32 *) (req + 1);
  528.  
  529.       req->reqType = opcode;
  530.       req->glxCode = X_GLXCreatePbuffer;
  531.       req->screen = config->screen;
  532.       req->fbconfig = config->fbconfigID;
  533.       req->pbuffer = id;
  534.       req->numAttribs = i + extra;
  535.  
  536.       if (!size_in_attribs) {
  537.          data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
  538.          data[(2 * i) + 1] = width;
  539.          data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
  540.          data[(2 * i) + 3] = height;
  541.          data += 4;
  542.       }
  543.    }
  544.    else {
  545.       xGLXVendorPrivateReq *vpreq;
  546.  
  547.       GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
  548.       data = (CARD32 *) (vpreq + 1);
  549.  
  550.       vpreq->reqType = opcode;
  551.       vpreq->glxCode = X_GLXVendorPrivate;
  552.       vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
  553.  
  554.       data[0] = config->screen;
  555.       data[1] = config->fbconfigID;
  556.       data[2] = id;
  557.       data[3] = width;
  558.       data[4] = height;
  559.       data += 5;
  560.    }
  561.  
  562.    (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
  563.  
  564.    UnlockDisplay(dpy);
  565.    SyncHandle();
  566.  
  567.    pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen),
  568.                           width, height, config->rgbBits);
  569.  
  570.    if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) {
  571.       CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
  572.       XFreePixmap(dpy, pixmap);
  573.       protocolDestroyDrawable(dpy, id, o);
  574.       id = None;
  575.    }
  576.  
  577.    return id;
  578. }
  579.  
  580. /**
  581.  * Destroy a pbuffer.
  582.  *
  583.  * This function is used to implement \c glXDestroyPbuffer and
  584.  * \c glXDestroyGLXPbufferSGIX.
  585.  *
  586.  * \note
  587.  * This function dynamically determines whether to use the SGIX_pbuffer
  588.  * version of the protocol or the GLX 1.3 version of the protocol.
  589.  */
  590. static void
  591. DestroyPbuffer(Display * dpy, GLXDrawable drawable)
  592. {
  593.    struct glx_display *priv = __glXInitialize(dpy);
  594.    CARD8 opcode;
  595.  
  596.    if ((dpy == NULL) || (drawable == 0)) {
  597.       return;
  598.    }
  599.  
  600.    opcode = __glXSetupForCommand(dpy);
  601.    if (!opcode)
  602.       return;
  603.  
  604.    LockDisplay(dpy);
  605.  
  606.    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  607.       xGLXDestroyPbufferReq *req;
  608.  
  609.       GetReq(GLXDestroyPbuffer, req);
  610.       req->reqType = opcode;
  611.       req->glxCode = X_GLXDestroyPbuffer;
  612.       req->pbuffer = (GLXPbuffer) drawable;
  613.    }
  614.    else {
  615.       xGLXVendorPrivateWithReplyReq *vpreq;
  616.       CARD32 *data;
  617.  
  618.       GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  619.       data = (CARD32 *) (vpreq + 1);
  620.  
  621.       data[0] = (CARD32) drawable;
  622.  
  623.       vpreq->reqType = opcode;
  624.       vpreq->glxCode = X_GLXVendorPrivateWithReply;
  625.       vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
  626.    }
  627.  
  628.    UnlockDisplay(dpy);
  629.    SyncHandle();
  630.  
  631.    DestroyDRIDrawable(dpy, drawable, GL_TRUE);
  632.  
  633.    return;
  634. }
  635.  
  636. /**
  637.  * Create a new pbuffer.
  638.  */
  639. _X_EXPORT GLXPbufferSGIX
  640. glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
  641.                         unsigned int width, unsigned int height,
  642.                         int *attrib_list)
  643. {
  644.    return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config,
  645.                                          width, height,
  646.                                          attrib_list, GL_FALSE);
  647. }
  648.  
  649. #endif /* GLX_USE_APPLEGL */
  650.  
  651. /**
  652.  * Create a new pbuffer.
  653.  */
  654. _X_EXPORT GLXPbuffer
  655. glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
  656. {
  657.    int i, width, height;
  658. #ifdef GLX_USE_APPLEGL
  659.    GLXPbuffer result;
  660.    int errorcode;
  661. #endif
  662.  
  663.    width = 0;
  664.    height = 0;
  665.  
  666.    WARN_ONCE_GLX_1_3(dpy, __func__);
  667.  
  668. #ifdef GLX_USE_APPLEGL
  669.    for (i = 0; attrib_list[i]; ++i) {
  670.       switch (attrib_list[i]) {
  671.       case GLX_PBUFFER_WIDTH:
  672.          width = attrib_list[i + 1];
  673.          ++i;
  674.          break;
  675.  
  676.       case GLX_PBUFFER_HEIGHT:
  677.          height = attrib_list[i + 1];
  678.          ++i;
  679.          break;
  680.  
  681.       case GLX_LARGEST_PBUFFER:
  682.          /* This is a hint we should probably handle, but how? */
  683.          ++i;
  684.          break;
  685.  
  686.       case GLX_PRESERVED_CONTENTS:
  687.          /* The contents are always preserved with AppleSGLX with CGL. */
  688.          ++i;
  689.          break;
  690.  
  691.       default:
  692.          return None;
  693.       }
  694.    }
  695.  
  696.    if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode,
  697.                                 &result)) {
  698.       /*
  699.        * apple_glx_pbuffer_create only sets the errorcode to core X11
  700.        * errors.
  701.        */
  702.       __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true);
  703.  
  704.       return None;
  705.    }
  706.  
  707.    return result;
  708. #else
  709.    for (i = 0; attrib_list[i * 2]; i++) {
  710.       switch (attrib_list[i * 2]) {
  711.       case GLX_PBUFFER_WIDTH:
  712.          width = attrib_list[i * 2 + 1];
  713.          break;
  714.       case GLX_PBUFFER_HEIGHT:
  715.          height = attrib_list[i * 2 + 1];
  716.          break;
  717.       }
  718.    }
  719.  
  720.    return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config,
  721.                                      width, height, attrib_list, GL_TRUE);
  722. #endif
  723. }
  724.  
  725.  
  726. /**
  727.  * Destroy an existing pbuffer.
  728.  */
  729. _X_EXPORT void
  730. glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
  731. {
  732. #ifdef GLX_USE_APPLEGL
  733.    if (apple_glx_pbuffer_destroy(dpy, pbuf)) {
  734.       __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false);
  735.    }
  736. #else
  737.    DestroyPbuffer(dpy, pbuf);
  738. #endif
  739. }
  740.  
  741.  
  742. /**
  743.  * Query an attribute of a drawable.
  744.  */
  745. _X_EXPORT void
  746. glXQueryDrawable(Display * dpy, GLXDrawable drawable,
  747.                  int attribute, unsigned int *value)
  748. {
  749.    WARN_ONCE_GLX_1_3(dpy, __func__);
  750. #ifdef GLX_USE_APPLEGL
  751.    Window root;
  752.    int x, y;
  753.    unsigned int width, height, bd, depth;
  754.  
  755.    if (apple_glx_pixmap_query(drawable, attribute, value))
  756.       return;                   /*done */
  757.  
  758.    if (apple_glx_pbuffer_query(drawable, attribute, value))
  759.       return;                   /*done */
  760.  
  761.    /*
  762.     * The OpenGL spec states that we should report GLXBadDrawable if
  763.     * the drawable is invalid, however doing so would require that we
  764.     * use XSetErrorHandler(), which is known to not be thread safe.
  765.     * If we use a round-trip call to validate the drawable, there could
  766.     * be a race, so instead we just opt in favor of letting the
  767.     * XGetGeometry request fail with a GetGeometry request X error
  768.     * rather than GLXBadDrawable, in what is hoped to be a rare
  769.     * case of an invalid drawable.  In practice most and possibly all
  770.     * X11 apps using GLX shouldn't notice a difference.
  771.     */
  772.    if (XGetGeometry
  773.        (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) {
  774.       switch (attribute) {
  775.       case GLX_WIDTH:
  776.          *value = width;
  777.          break;
  778.  
  779.       case GLX_HEIGHT:
  780.          *value = height;
  781.          break;
  782.       }
  783.    }
  784. #else
  785.    GetDrawableAttribute(dpy, drawable, attribute, value);
  786. #endif
  787. }
  788.  
  789.  
  790. #ifndef GLX_USE_APPLEGL
  791. /**
  792.  * Query an attribute of a pbuffer.
  793.  */
  794. _X_EXPORT int
  795. glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
  796.                        int attribute, unsigned int *value)
  797. {
  798.    return GetDrawableAttribute(dpy, drawable, attribute, value);
  799. }
  800. #endif
  801.  
  802. /**
  803.  * Select the event mask for a drawable.
  804.  */
  805. _X_EXPORT void
  806. glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
  807. {
  808. #ifdef GLX_USE_APPLEGL
  809.    XWindowAttributes xwattr;
  810.  
  811.    if (apple_glx_pbuffer_set_event_mask(drawable, mask))
  812.       return;                   /*done */
  813.  
  814.    /*
  815.     * The spec allows a window, but currently there are no valid
  816.     * events for a window, so do nothing.
  817.     */
  818.    if (XGetWindowAttributes(dpy, drawable, &xwattr))
  819.       return;                   /*done */
  820.    /* The drawable seems to be invalid.  Report an error. */
  821.  
  822.    __glXSendError(dpy, GLXBadDrawable, drawable,
  823.                   X_GLXChangeDrawableAttributes, false);
  824. #else
  825.    CARD32 attribs[2];
  826.  
  827.    attribs[0] = (CARD32) GLX_EVENT_MASK;
  828.    attribs[1] = (CARD32) mask;
  829.  
  830.    ChangeDrawableAttribute(dpy, drawable, attribs, 1);
  831. #endif
  832. }
  833.  
  834.  
  835. /**
  836.  * Get the selected event mask for a drawable.
  837.  */
  838. _X_EXPORT void
  839. glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
  840. {
  841. #ifdef GLX_USE_APPLEGL
  842.    XWindowAttributes xwattr;
  843.  
  844.    if (apple_glx_pbuffer_get_event_mask(drawable, mask))
  845.       return;                   /*done */
  846.  
  847.    /*
  848.     * The spec allows a window, but currently there are no valid
  849.     * events for a window, so do nothing, but set the mask to 0.
  850.     */
  851.    if (XGetWindowAttributes(dpy, drawable, &xwattr)) {
  852.       /* The window is valid, so set the mask to 0. */
  853.       *mask = 0;
  854.       return;                   /*done */
  855.    }
  856.    /* The drawable seems to be invalid.  Report an error. */
  857.  
  858.    __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes,
  859.                   true);
  860. #else
  861.    unsigned int value;
  862.  
  863.  
  864.    /* The non-sense with value is required because on LP64 platforms
  865.     * sizeof(unsigned int) != sizeof(unsigned long).  On little-endian
  866.     * we could just type-cast the pointer, but why?
  867.     */
  868.  
  869.    GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
  870.    *mask = value;
  871. #endif
  872. }
  873.  
  874.  
  875. _X_EXPORT GLXPixmap
  876. glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
  877.                 const int *attrib_list)
  878. {
  879.    WARN_ONCE_GLX_1_3(dpy, __func__);
  880.  
  881. #ifdef GLX_USE_APPLEGL
  882.    const struct glx_config *modes = (const struct glx_config *) config;
  883.  
  884.    if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes))
  885.       return None;
  886.  
  887.    return pixmap;
  888. #else
  889.    return CreateDrawable(dpy, (struct glx_config *) config,
  890.                          (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
  891. #endif
  892. }
  893.  
  894.  
  895. _X_EXPORT GLXWindow
  896. glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
  897.                 const int *attrib_list)
  898. {
  899.    WARN_ONCE_GLX_1_3(dpy, __func__);
  900. #ifdef GLX_USE_APPLEGL
  901.    XWindowAttributes xwattr;
  902.    XVisualInfo *visinfo;
  903.  
  904.    (void) attrib_list;          /*unused according to GLX 1.4 */
  905.  
  906.    XGetWindowAttributes(dpy, win, &xwattr);
  907.  
  908.    visinfo = glXGetVisualFromFBConfig(dpy, config);
  909.  
  910.    if (NULL == visinfo) {
  911.       __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false);
  912.       return None;
  913.    }
  914.  
  915.    if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) {
  916.       __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true);
  917.       return None;
  918.    }
  919.  
  920.    free(visinfo);
  921.  
  922.    return win;
  923. #else
  924.    return CreateDrawable(dpy, (struct glx_config *) config,
  925.                          (Drawable) win, attrib_list, X_GLXCreateWindow);
  926. #endif
  927. }
  928.  
  929.  
  930. _X_EXPORT void
  931. glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
  932. {
  933.    WARN_ONCE_GLX_1_3(dpy, __func__);
  934. #ifdef GLX_USE_APPLEGL
  935.    if (apple_glx_pixmap_destroy(dpy, pixmap))
  936.       __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false);
  937. #else
  938.    DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
  939. #endif
  940. }
  941.  
  942.  
  943. _X_EXPORT void
  944. glXDestroyWindow(Display * dpy, GLXWindow win)
  945. {
  946.    WARN_ONCE_GLX_1_3(dpy, __func__);
  947. #ifndef GLX_USE_APPLEGL
  948.    DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
  949. #endif
  950. }
  951.  
  952. #ifndef GLX_USE_APPLEGL
  953. _X_EXPORT
  954. GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
  955.                (Display * dpy, GLXPbufferSGIX pbuf),
  956.                (dpy, pbuf), glXDestroyPbuffer)
  957.  
  958. _X_EXPORT
  959. GLX_ALIAS_VOID(glXSelectEventSGIX,
  960.                (Display * dpy, GLXDrawable drawable,
  961.                 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
  962.  
  963. _X_EXPORT
  964. GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
  965.                (Display * dpy, GLXDrawable drawable,
  966.                 unsigned long *mask), (dpy, drawable, mask),
  967.                glXGetSelectedEvent)
  968. #endif
  969.