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