OSDN Git Service

nv50,nvc0: fix depth range when halfz is enabled
[android-x86/external-mesa.git] / src / glx / glx_pbuffer.c
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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC 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 _GLX_PUBLIC
997 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
998                (Display * dpy, GLXPbufferSGIX pbuf),
999                (dpy, pbuf), glXDestroyPbuffer)
1000
1001 _GLX_PUBLIC
1002 GLX_ALIAS_VOID(glXSelectEventSGIX,
1003                (Display * dpy, GLXDrawable drawable,
1004                 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
1005
1006 _GLX_PUBLIC
1007 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
1008                (Display * dpy, GLXDrawable drawable,
1009                 unsigned long *mask), (dpy, drawable, mask),
1010                glXGetSelectedEvent)
1011 #endif