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