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/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 && 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 ((priv == NULL) || (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.    if (priv == NULL) {
  201.       fprintf(stderr, "failed to create drawable\n");
  202.       return GL_FALSE;
  203.    }
  204.  
  205.    psc = priv->screens[config->screen];
  206.    if (psc->driScreen == NULL)
  207.       return GL_TRUE;
  208.  
  209.    pdraw = psc->driScreen->createDrawable(psc, drawable,
  210.                                           glxdrawable, config);
  211.    if (pdraw == NULL) {
  212.       fprintf(stderr, "failed to create drawable\n");
  213.       return GL_FALSE;
  214.    }
  215.  
  216.    if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) {
  217.       (*pdraw->destroyDrawable) (pdraw);
  218.       return GL_FALSE;
  219.    }
  220.  
  221.    pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs);
  222.    pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs);
  223.  
  224.    return GL_TRUE;
  225. }
  226.  
  227. static void
  228. DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
  229. {
  230.    struct glx_display *const priv = __glXInitialize(dpy);
  231.    __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
  232.    XID xid;
  233.  
  234.    if (priv != NULL && pdraw != NULL) {
  235.       xid = pdraw->xDrawable;
  236.       (*pdraw->destroyDrawable) (pdraw);
  237.       __glxHashDelete(priv->drawHash, drawable);
  238.       if (destroy_xdrawable)
  239.          XFreePixmap(priv->dpy, xid);
  240.    }
  241. }
  242.  
  243. #else
  244.  
  245. static GLboolean
  246. CreateDRIDrawable(Display *dpy, const struct glx_config * fbconfig,
  247.                   XID drawable, XID glxdrawable,
  248.                   const int *attrib_list, size_t num_attribs)
  249. {
  250.     return GL_TRUE;
  251. }
  252.  
  253. static void
  254. DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable)
  255. {
  256. }
  257.  
  258. #endif
  259.  
  260. /**
  261.  * Get a drawable's attribute.
  262.  *
  263.  * This function is used to implement \c glXGetSelectedEvent and
  264.  * \c glXGetSelectedEventSGIX.
  265.  *
  266.  * \note
  267.  * This function dynamically determines whether to use the SGIX_pbuffer
  268.  * version of the protocol or the GLX 1.3 version of the protocol.
  269.  *
  270.  * \todo
  271.  * The number of attributes returned is likely to be small, probably less than
  272.  * 10.  Given that, this routine should try to use an array on the stack to
  273.  * capture the reply rather than always calling Xmalloc.
  274.  */
  275. static int
  276. GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
  277.                      int attribute, unsigned int *value)
  278. {
  279.    struct glx_display *priv;
  280.    xGLXGetDrawableAttributesReply reply;
  281.    CARD32 *data;
  282.    CARD8 opcode;
  283.    unsigned int length;
  284.    unsigned int i;
  285.    unsigned int num_attributes;
  286.    GLboolean use_glx_1_3;
  287.  
  288. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  289.    __GLXDRIdrawable *pdraw;
  290. #endif
  291.  
  292.    if (dpy == NULL)
  293.       return 0;
  294.  
  295.    /* Page 38 (page 52 of the PDF) of glxencode1.3.pdf says:
  296.     *
  297.     *     "If drawable is not a valid GLX drawable, a GLXBadDrawable error is
  298.     *     generated."
  299.     */
  300.    if (drawable == 0) {
  301.       __glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false);
  302.       return 0;
  303.    }
  304.  
  305.    priv = __glXInitialize(dpy);
  306.    if (priv == NULL)
  307.       return 0;
  308.  
  309.    use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
  310.  
  311.    *value = 0;
  312.  
  313.  
  314.    opcode = __glXSetupForCommand(dpy);
  315.    if (!opcode)
  316.       return 0;
  317.  
  318. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  319.    pdraw = GetGLXDRIDrawable(dpy, drawable);
  320.  
  321.    if (attribute == GLX_BACK_BUFFER_AGE_EXT) {
  322.       struct glx_context *gc = __glXGetCurrentContext();
  323.       struct glx_screen *psc;
  324.  
  325.       /* The GLX_EXT_buffer_age spec says:
  326.        *
  327.        *   "If querying GLX_BACK_BUFFER_AGE_EXT and <draw> is not bound to
  328.        *   the calling thread's current context a GLXBadDrawable error is
  329.        *   generated."
  330.        */
  331.       if (pdraw == NULL || gc == NULL || gc->currentDpy != dpy ||
  332.          (gc->currentDrawable != drawable &&
  333.          gc->currentReadable != drawable)) {
  334.          __glXSendError(dpy, GLXBadDrawable, drawable,
  335.                         X_GLXGetDrawableAttributes, false);
  336.          return 0;
  337.       }
  338.  
  339.       psc = pdraw->psc;
  340.  
  341.       if (psc->driScreen->getBufferAge != NULL)
  342.          *value = psc->driScreen->getBufferAge(pdraw);
  343.  
  344.       return 0;
  345.    }
  346. #endif
  347.  
  348.    LockDisplay(dpy);
  349.  
  350.    if (use_glx_1_3) {
  351.       xGLXGetDrawableAttributesReq *req;
  352.  
  353.       GetReq(GLXGetDrawableAttributes, req);
  354.       req->reqType = opcode;
  355.       req->glxCode = X_GLXGetDrawableAttributes;
  356.       req->drawable = drawable;
  357.    }
  358.    else {
  359.       xGLXVendorPrivateWithReplyReq *vpreq;
  360.  
  361.       GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  362.       data = (CARD32 *) (vpreq + 1);
  363.       data[0] = (CARD32) drawable;
  364.  
  365.       vpreq->reqType = opcode;
  366.       vpreq->glxCode = X_GLXVendorPrivateWithReply;
  367.       vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
  368.    }
  369.  
  370.    _XReply(dpy, (xReply *) & reply, 0, False);
  371.  
  372.    if (reply.type == X_Error) {
  373.       UnlockDisplay(dpy);
  374.       SyncHandle();
  375.       return 0;
  376.    }
  377.  
  378.    length = reply.length;
  379.    if (length) {
  380.       num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
  381.       data = malloc(length * sizeof(CARD32));
  382.       if (data == NULL) {
  383.          /* Throw data on the floor */
  384.          _XEatData(dpy, length);
  385.       }
  386.       else {
  387.          _XRead(dpy, (char *) data, length * sizeof(CARD32));
  388.  
  389.          /* Search the set of returned attributes for the attribute requested by
  390.           * the caller.
  391.           */
  392.          for (i = 0; i < num_attributes; i++) {
  393.             if (data[i * 2] == attribute) {
  394.                *value = data[(i * 2) + 1];
  395.                break;
  396.             }
  397.          }
  398.  
  399. #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
  400.          if (pdraw != NULL) {
  401.             if (!pdraw->textureTarget)
  402.                pdraw->textureTarget =
  403.                   determineTextureTarget((const int *) data, num_attributes);
  404.             if (!pdraw->textureFormat)
  405.                pdraw->textureFormat =
  406.                   determineTextureFormat((const int *) data, num_attributes);
  407.          }
  408. #endif
  409.  
  410.          free(data);
  411.       }
  412.    }
  413.  
  414.    UnlockDisplay(dpy);
  415.    SyncHandle();
  416.  
  417.    return 0;
  418. }
  419.  
  420. static void
  421. protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
  422. {
  423.    xGLXDestroyPbufferReq *req;
  424.    CARD8 opcode;
  425.  
  426.    opcode = __glXSetupForCommand(dpy);
  427.    if (!opcode)
  428.       return;
  429.  
  430.    LockDisplay(dpy);
  431.  
  432.    GetReq(GLXDestroyPbuffer, req);
  433.    req->reqType = opcode;
  434.    req->glxCode = glxCode;
  435.    req->pbuffer = (GLXPbuffer) drawable;
  436.  
  437.    UnlockDisplay(dpy);
  438.    SyncHandle();
  439. }
  440.  
  441. /**
  442.  * Create a non-pbuffer GLX drawable.
  443.  */
  444. static GLXDrawable
  445. CreateDrawable(Display *dpy, struct glx_config *config,
  446.                Drawable drawable, const int *attrib_list, CARD8 glxCode)
  447. {
  448.    xGLXCreateWindowReq *req;
  449.    struct glx_drawable *glxDraw;
  450.    CARD32 *data;
  451.    unsigned int i;
  452.    CARD8 opcode;
  453.    GLXDrawable xid;
  454.  
  455.    i = 0;
  456.    if (attrib_list) {
  457.       while (attrib_list[i * 2] != None)
  458.          i++;
  459.    }
  460.  
  461.    opcode = __glXSetupForCommand(dpy);
  462.    if (!opcode)
  463.       return None;
  464.  
  465.    glxDraw = malloc(sizeof(*glxDraw));
  466.    if (!glxDraw)
  467.       return None;
  468.  
  469.    LockDisplay(dpy);
  470.    GetReqExtra(GLXCreateWindow, 8 * i, req);
  471.    data = (CARD32 *) (req + 1);
  472.  
  473.    req->reqType = opcode;
  474.    req->glxCode = glxCode;
  475.    req->screen = config->screen;
  476.    req->fbconfig = config->fbconfigID;
  477.    req->window = drawable;
  478.    req->glxwindow = xid = XAllocID(dpy);
  479.    req->numAttribs = i;
  480.  
  481.    if (attrib_list)
  482.       memcpy(data, attrib_list, 8 * i);
  483.  
  484.    UnlockDisplay(dpy);
  485.    SyncHandle();
  486.  
  487.    if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) {
  488.       free(glxDraw);
  489.       return None;
  490.    }
  491.  
  492.    if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
  493.       if (glxCode == X_GLXCreatePixmap)
  494.          glxCode = X_GLXDestroyPixmap;
  495.       else
  496.          glxCode = X_GLXDestroyWindow;
  497.       protocolDestroyDrawable(dpy, xid, glxCode);
  498.       xid = None;
  499.    }
  500.  
  501.    return xid;
  502. }
  503.  
  504.  
  505. /**
  506.  * Destroy a non-pbuffer GLX drawable.
  507.  */
  508. static void
  509. DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
  510. {
  511.    if ((dpy == NULL) || (drawable == 0)) {
  512.       return;
  513.    }
  514.  
  515.    protocolDestroyDrawable(dpy, drawable, glxCode);
  516.  
  517.    DestroyGLXDrawable(dpy, drawable);
  518.    DestroyDRIDrawable(dpy, drawable, GL_FALSE);
  519.  
  520.    return;
  521. }
  522.  
  523.  
  524. /**
  525.  * Create a pbuffer.
  526.  *
  527.  * This function is used to implement \c glXCreatePbuffer and
  528.  * \c glXCreateGLXPbufferSGIX.
  529.  *
  530.  * \note
  531.  * This function dynamically determines whether to use the SGIX_pbuffer
  532.  * version of the protocol or the GLX 1.3 version of the protocol.
  533.  */
  534. static GLXDrawable
  535. CreatePbuffer(Display * dpy, struct glx_config *config,
  536.               unsigned int width, unsigned int height,
  537.               const int *attrib_list, GLboolean size_in_attribs)
  538. {
  539.    struct glx_display *priv = __glXInitialize(dpy);
  540.    GLXDrawable id = 0;
  541.    CARD32 *data;
  542.    CARD8 opcode;
  543.    unsigned int i;
  544.    Pixmap pixmap;
  545.    GLboolean glx_1_3 = GL_FALSE;
  546.  
  547.    if (priv == NULL)
  548.       return None;
  549.  
  550.    i = 0;
  551.    if (attrib_list) {
  552.       while (attrib_list[i * 2])
  553.          i++;
  554.    }
  555.  
  556.    opcode = __glXSetupForCommand(dpy);
  557.    if (!opcode)
  558.       return None;
  559.  
  560.    LockDisplay(dpy);
  561.    id = XAllocID(dpy);
  562.  
  563.    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  564.       xGLXCreatePbufferReq *req;
  565.       unsigned int extra = (size_in_attribs) ? 0 : 2;
  566.  
  567.       glx_1_3 = GL_TRUE;
  568.  
  569.       GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
  570.       data = (CARD32 *) (req + 1);
  571.  
  572.       req->reqType = opcode;
  573.       req->glxCode = X_GLXCreatePbuffer;
  574.       req->screen = config->screen;
  575.       req->fbconfig = config->fbconfigID;
  576.       req->pbuffer = id;
  577.       req->numAttribs = i + extra;
  578.  
  579.       if (!size_in_attribs) {
  580.          data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
  581.          data[(2 * i) + 1] = width;
  582.          data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
  583.          data[(2 * i) + 3] = height;
  584.          data += 4;
  585.       }
  586.    }
  587.    else {
  588.       xGLXVendorPrivateReq *vpreq;
  589.  
  590.       GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
  591.       data = (CARD32 *) (vpreq + 1);
  592.  
  593.       vpreq->reqType = opcode;
  594.       vpreq->glxCode = X_GLXVendorPrivate;
  595.       vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
  596.  
  597.       data[0] = config->screen;
  598.       data[1] = config->fbconfigID;
  599.       data[2] = id;
  600.       data[3] = width;
  601.       data[4] = height;
  602.       data += 5;
  603.    }
  604.  
  605.    (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
  606.  
  607.    UnlockDisplay(dpy);
  608.    SyncHandle();
  609.  
  610.    pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen),
  611.                           width, height, config->rgbBits);
  612.  
  613.    if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) {
  614.       CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
  615.       XFreePixmap(dpy, pixmap);
  616.       protocolDestroyDrawable(dpy, id, o);
  617.       id = None;
  618.    }
  619.  
  620.    return id;
  621. }
  622.  
  623. /**
  624.  * Destroy a pbuffer.
  625.  *
  626.  * This function is used to implement \c glXDestroyPbuffer and
  627.  * \c glXDestroyGLXPbufferSGIX.
  628.  *
  629.  * \note
  630.  * This function dynamically determines whether to use the SGIX_pbuffer
  631.  * version of the protocol or the GLX 1.3 version of the protocol.
  632.  */
  633. static void
  634. DestroyPbuffer(Display * dpy, GLXDrawable drawable)
  635. {
  636.    struct glx_display *priv = __glXInitialize(dpy);
  637.    CARD8 opcode;
  638.  
  639.    if ((priv == NULL) || (dpy == NULL) || (drawable == 0)) {
  640.       return;
  641.    }
  642.  
  643.    opcode = __glXSetupForCommand(dpy);
  644.    if (!opcode)
  645.       return;
  646.  
  647.    LockDisplay(dpy);
  648.  
  649.    if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  650.       xGLXDestroyPbufferReq *req;
  651.  
  652.       GetReq(GLXDestroyPbuffer, req);
  653.       req->reqType = opcode;
  654.       req->glxCode = X_GLXDestroyPbuffer;
  655.       req->pbuffer = (GLXPbuffer) drawable;
  656.    }
  657.    else {
  658.       xGLXVendorPrivateWithReplyReq *vpreq;
  659.       CARD32 *data;
  660.  
  661.       GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
  662.       data = (CARD32 *) (vpreq + 1);
  663.  
  664.       data[0] = (CARD32) drawable;
  665.  
  666.       vpreq->reqType = opcode;
  667.       vpreq->glxCode = X_GLXVendorPrivateWithReply;
  668.       vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
  669.    }
  670.  
  671.    UnlockDisplay(dpy);
  672.    SyncHandle();
  673.  
  674.    DestroyDRIDrawable(dpy, drawable, GL_TRUE);
  675.  
  676.    return;
  677. }
  678.  
  679. /**
  680.  * Create a new pbuffer.
  681.  */
  682. _X_EXPORT GLXPbufferSGIX
  683. glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
  684.                         unsigned int width, unsigned int height,
  685.                         int *attrib_list)
  686. {
  687.    return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config,
  688.                                          width, height,
  689.                                          attrib_list, GL_FALSE);
  690. }
  691.  
  692. #endif /* GLX_USE_APPLEGL */
  693.  
  694. /**
  695.  * Create a new pbuffer.
  696.  */
  697. _X_EXPORT GLXPbuffer
  698. glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
  699. {
  700.    int i, width, height;
  701. #ifdef GLX_USE_APPLEGL
  702.    GLXPbuffer result;
  703.    int errorcode;
  704. #endif
  705.  
  706.    width = 0;
  707.    height = 0;
  708.  
  709.    WARN_ONCE_GLX_1_3(dpy, __func__);
  710.  
  711. #ifdef GLX_USE_APPLEGL
  712.    for (i = 0; attrib_list[i]; ++i) {
  713.       switch (attrib_list[i]) {
  714.       case GLX_PBUFFER_WIDTH:
  715.          width = attrib_list[i + 1];
  716.          ++i;
  717.          break;
  718.  
  719.       case GLX_PBUFFER_HEIGHT:
  720.          height = attrib_list[i + 1];
  721.          ++i;
  722.          break;
  723.  
  724.       case GLX_LARGEST_PBUFFER:
  725.          /* This is a hint we should probably handle, but how? */
  726.          ++i;
  727.          break;
  728.  
  729.       case GLX_PRESERVED_CONTENTS:
  730.          /* The contents are always preserved with AppleSGLX with CGL. */
  731.          ++i;
  732.          break;
  733.  
  734.       default:
  735.          return None;
  736.       }
  737.    }
  738.  
  739.    if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode,
  740.                                 &result)) {
  741.       /*
  742.        * apple_glx_pbuffer_create only sets the errorcode to core X11
  743.        * errors.
  744.        */
  745.       __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true);
  746.  
  747.       return None;
  748.    }
  749.  
  750.    return result;
  751. #else
  752.    for (i = 0; attrib_list[i * 2]; i++) {
  753.       switch (attrib_list[i * 2]) {
  754.       case GLX_PBUFFER_WIDTH:
  755.          width = attrib_list[i * 2 + 1];
  756.          break;
  757.       case GLX_PBUFFER_HEIGHT:
  758.          height = attrib_list[i * 2 + 1];
  759.          break;
  760.       }
  761.    }
  762.  
  763.    return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config,
  764.                                      width, height, attrib_list, GL_TRUE);
  765. #endif
  766. }
  767.  
  768.  
  769. /**
  770.  * Destroy an existing pbuffer.
  771.  */
  772. _X_EXPORT void
  773. glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
  774. {
  775. #ifdef GLX_USE_APPLEGL
  776.    if (apple_glx_pbuffer_destroy(dpy, pbuf)) {
  777.       __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false);
  778.    }
  779. #else
  780.    DestroyPbuffer(dpy, pbuf);
  781. #endif
  782. }
  783.  
  784.  
  785. /**
  786.  * Query an attribute of a drawable.
  787.  */
  788. _X_EXPORT void
  789. glXQueryDrawable(Display * dpy, GLXDrawable drawable,
  790.                  int attribute, unsigned int *value)
  791. {
  792.    WARN_ONCE_GLX_1_3(dpy, __func__);
  793. #ifdef GLX_USE_APPLEGL
  794.    Window root;
  795.    int x, y;
  796.    unsigned int width, height, bd, depth;
  797.  
  798.    if (apple_glx_pixmap_query(drawable, attribute, value))
  799.       return;                   /*done */
  800.  
  801.    if (apple_glx_pbuffer_query(drawable, attribute, value))
  802.       return;                   /*done */
  803.  
  804.    /*
  805.     * The OpenGL spec states that we should report GLXBadDrawable if
  806.     * the drawable is invalid, however doing so would require that we
  807.     * use XSetErrorHandler(), which is known to not be thread safe.
  808.     * If we use a round-trip call to validate the drawable, there could
  809.     * be a race, so instead we just opt in favor of letting the
  810.     * XGetGeometry request fail with a GetGeometry request X error
  811.     * rather than GLXBadDrawable, in what is hoped to be a rare
  812.     * case of an invalid drawable.  In practice most and possibly all
  813.     * X11 apps using GLX shouldn't notice a difference.
  814.     */
  815.    if (XGetGeometry
  816.        (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) {
  817.       switch (attribute) {
  818.       case GLX_WIDTH:
  819.          *value = width;
  820.          break;
  821.  
  822.       case GLX_HEIGHT:
  823.          *value = height;
  824.          break;
  825.       }
  826.    }
  827. #else
  828.    GetDrawableAttribute(dpy, drawable, attribute, value);
  829. #endif
  830. }
  831.  
  832.  
  833. #ifndef GLX_USE_APPLEGL
  834. /**
  835.  * Query an attribute of a pbuffer.
  836.  */
  837. _X_EXPORT int
  838. glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
  839.                        int attribute, unsigned int *value)
  840. {
  841.    return GetDrawableAttribute(dpy, drawable, attribute, value);
  842. }
  843. #endif
  844.  
  845. /**
  846.  * Select the event mask for a drawable.
  847.  */
  848. _X_EXPORT void
  849. glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
  850. {
  851. #ifdef GLX_USE_APPLEGL
  852.    XWindowAttributes xwattr;
  853.  
  854.    if (apple_glx_pbuffer_set_event_mask(drawable, mask))
  855.       return;                   /*done */
  856.  
  857.    /*
  858.     * The spec allows a window, but currently there are no valid
  859.     * events for a window, so do nothing.
  860.     */
  861.    if (XGetWindowAttributes(dpy, drawable, &xwattr))
  862.       return;                   /*done */
  863.    /* The drawable seems to be invalid.  Report an error. */
  864.  
  865.    __glXSendError(dpy, GLXBadDrawable, drawable,
  866.                   X_GLXChangeDrawableAttributes, false);
  867. #else
  868.    CARD32 attribs[2];
  869.  
  870.    attribs[0] = (CARD32) GLX_EVENT_MASK;
  871.    attribs[1] = (CARD32) mask;
  872.  
  873.    ChangeDrawableAttribute(dpy, drawable, attribs, 1);
  874. #endif
  875. }
  876.  
  877.  
  878. /**
  879.  * Get the selected event mask for a drawable.
  880.  */
  881. _X_EXPORT void
  882. glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
  883. {
  884. #ifdef GLX_USE_APPLEGL
  885.    XWindowAttributes xwattr;
  886.  
  887.    if (apple_glx_pbuffer_get_event_mask(drawable, mask))
  888.       return;                   /*done */
  889.  
  890.    /*
  891.     * The spec allows a window, but currently there are no valid
  892.     * events for a window, so do nothing, but set the mask to 0.
  893.     */
  894.    if (XGetWindowAttributes(dpy, drawable, &xwattr)) {
  895.       /* The window is valid, so set the mask to 0. */
  896.       *mask = 0;
  897.       return;                   /*done */
  898.    }
  899.    /* The drawable seems to be invalid.  Report an error. */
  900.  
  901.    __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes,
  902.                   true);
  903. #else
  904.    unsigned int value;
  905.  
  906.  
  907.    /* The non-sense with value is required because on LP64 platforms
  908.     * sizeof(unsigned int) != sizeof(unsigned long).  On little-endian
  909.     * we could just type-cast the pointer, but why?
  910.     */
  911.  
  912.    GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
  913.    *mask = value;
  914. #endif
  915. }
  916.  
  917.  
  918. _X_EXPORT GLXPixmap
  919. glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
  920.                 const int *attrib_list)
  921. {
  922.    WARN_ONCE_GLX_1_3(dpy, __func__);
  923.  
  924. #ifdef GLX_USE_APPLEGL
  925.    const struct glx_config *modes = (const struct glx_config *) config;
  926.  
  927.    if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes))
  928.       return None;
  929.  
  930.    return pixmap;
  931. #else
  932.    return CreateDrawable(dpy, (struct glx_config *) config,
  933.                          (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
  934. #endif
  935. }
  936.  
  937.  
  938. _X_EXPORT GLXWindow
  939. glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
  940.                 const int *attrib_list)
  941. {
  942.    WARN_ONCE_GLX_1_3(dpy, __func__);
  943. #ifdef GLX_USE_APPLEGL
  944.    XWindowAttributes xwattr;
  945.    XVisualInfo *visinfo;
  946.  
  947.    (void) attrib_list;          /*unused according to GLX 1.4 */
  948.  
  949.    XGetWindowAttributes(dpy, win, &xwattr);
  950.  
  951.    visinfo = glXGetVisualFromFBConfig(dpy, config);
  952.  
  953.    if (NULL == visinfo) {
  954.       __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false);
  955.       return None;
  956.    }
  957.  
  958.    if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) {
  959.       __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true);
  960.       return None;
  961.    }
  962.  
  963.    free(visinfo);
  964.  
  965.    return win;
  966. #else
  967.    return CreateDrawable(dpy, (struct glx_config *) config,
  968.                          (Drawable) win, attrib_list, X_GLXCreateWindow);
  969. #endif
  970. }
  971.  
  972.  
  973. _X_EXPORT void
  974. glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
  975. {
  976.    WARN_ONCE_GLX_1_3(dpy, __func__);
  977. #ifdef GLX_USE_APPLEGL
  978.    if (apple_glx_pixmap_destroy(dpy, pixmap))
  979.       __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false);
  980. #else
  981.    DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
  982. #endif
  983. }
  984.  
  985.  
  986. _X_EXPORT void
  987. glXDestroyWindow(Display * dpy, GLXWindow win)
  988. {
  989.    WARN_ONCE_GLX_1_3(dpy, __func__);
  990. #ifndef GLX_USE_APPLEGL
  991.    DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
  992. #endif
  993. }
  994.  
  995. #ifndef GLX_USE_APPLEGL
  996. _X_EXPORT
  997. GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
  998.                (Display * dpy, GLXPbufferSGIX pbuf),
  999.                (dpy, pbuf), glXDestroyPbuffer)
  1000.  
  1001. _X_EXPORT
  1002. GLX_ALIAS_VOID(glXSelectEventSGIX,
  1003.                (Display * dpy, GLXDrawable drawable,
  1004.                 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
  1005.  
  1006. _X_EXPORT
  1007. GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
  1008.                (Display * dpy, GLXDrawable drawable,
  1009.                 unsigned long *mask), (dpy, drawable, mask),
  1010.                glXGetSelectedEvent)
  1011. #endif
  1012.