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