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