• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
warn_GLX_1_3(Display * dpy,const char * function_name)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
ChangeDrawableAttribute(Display * dpy,GLXDrawable drawable,const CARD32 * attribs,size_t num_attribs)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
determineTextureTarget(const int * attribs,int numAttribs)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
determineTextureFormat(const int * attribs,int numAttribs)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
CreateDRIDrawable(Display * dpy,struct glx_config * config,XID drawable,XID glxdrawable,const int * attrib_list,size_t num_attribs)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
DestroyDRIDrawable(Display * dpy,GLXDrawable drawable,int destroy_xdrawable)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
CreateDRIDrawable(Display * dpy,const struct glx_config * fbconfig,XID drawable,XID glxdrawable,const int * attrib_list,size_t num_attribs)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
DestroyDRIDrawable(Display * dpy,GLXDrawable drawable,int destroy_xdrawable)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
GetDrawableAttribute(Display * dpy,GLXDrawable drawable,int attribute,unsigned int * value)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 == &dummyContext || 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
protocolDestroyDrawable(Display * dpy,GLXDrawable drawable,CARD32 glxCode)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
CreateDrawable(Display * dpy,struct glx_config * config,Drawable drawable,const int * attrib_list,CARD8 glxCode)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
DestroyDrawable(Display * dpy,GLXDrawable drawable,CARD32 glxCode)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
CreatePbuffer(Display * dpy,struct glx_config * config,unsigned int width,unsigned int height,const int * attrib_list,GLboolean size_in_attribs)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
DestroyPbuffer(Display * dpy,GLXDrawable drawable)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
glXCreateGLXPbufferSGIX(Display * dpy,GLXFBConfigSGIX config,unsigned int width,unsigned int height,int * attrib_list)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
glXCreatePbuffer(Display * dpy,GLXFBConfig config,const int * attrib_list)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
glXDestroyPbuffer(Display * dpy,GLXPbuffer pbuf)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
glXQueryDrawable(Display * dpy,GLXDrawable drawable,int attribute,unsigned int * value)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
glXQueryGLXPbufferSGIX(Display * dpy,GLXPbufferSGIX drawable,int attribute,unsigned int * value)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
glXSelectEvent(Display * dpy,GLXDrawable drawable,unsigned long mask)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
glXGetSelectedEvent(Display * dpy,GLXDrawable drawable,unsigned long * mask)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
glXCreatePixmap(Display * dpy,GLXFBConfig config,Pixmap pixmap,const int * attrib_list)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
glXCreateWindow(Display * dpy,GLXFBConfig config,Window win,const int * attrib_list)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
glXDestroyPixmap(Display * dpy,GLXPixmap pixmap)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
glXDestroyWindow(Display * dpy,GLXWindow win)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 _GLX_PUBLIC
996 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
997                (Display * dpy, GLXPbufferSGIX pbuf),
998                (dpy, pbuf), glXDestroyPbuffer)
999 
1000 _GLX_PUBLIC
1001 GLX_ALIAS_VOID(glXSelectEventSGIX,
1002                (Display * dpy, GLXDrawable drawable,
1003                 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
1004 
1005 _GLX_PUBLIC
1006 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
1007                (Display * dpy, GLXDrawable drawable,
1008                 unsigned long *mask), (dpy, drawable, mask),
1009                glXGetSelectedEvent)
1010