glx: Add some missing null checks in glx_pbuffer.c
[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 #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 (dpy == NULL)
289 return 0;
290
291 /* Page 38 (page 52 of the PDF) of glxencode1.3.pdf says:
292 *
293 * "If drawable is not a valid GLX drawable, a GLXBadDrawable error is
294 * generated."
295 */
296 if (drawable == 0) {
297 __glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false);
298 return 0;
299 }
300
301 priv = __glXInitialize(dpy);
302 if (priv == NULL)
303 return 0;
304
305 use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3));
306
307 *value = 0;
308
309
310 opcode = __glXSetupForCommand(dpy);
311 if (!opcode)
312 return 0;
313
314 LockDisplay(dpy);
315
316 if (use_glx_1_3) {
317 xGLXGetDrawableAttributesReq *req;
318
319 GetReq(GLXGetDrawableAttributes, req);
320 req->reqType = opcode;
321 req->glxCode = X_GLXGetDrawableAttributes;
322 req->drawable = drawable;
323 }
324 else {
325 xGLXVendorPrivateWithReplyReq *vpreq;
326
327 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
328 data = (CARD32 *) (vpreq + 1);
329 data[0] = (CARD32) drawable;
330
331 vpreq->reqType = opcode;
332 vpreq->glxCode = X_GLXVendorPrivateWithReply;
333 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX;
334 }
335
336 _XReply(dpy, (xReply *) & reply, 0, False);
337
338 if (reply.type == X_Error) {
339 UnlockDisplay(dpy);
340 SyncHandle();
341 return 0;
342 }
343
344 length = reply.length;
345 if (length) {
346 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2;
347 data = malloc(length * sizeof(CARD32));
348 if (data == NULL) {
349 /* Throw data on the floor */
350 _XEatData(dpy, length);
351 }
352 else {
353 _XRead(dpy, (char *) data, length * sizeof(CARD32));
354
355 /* Search the set of returned attributes for the attribute requested by
356 * the caller.
357 */
358 for (i = 0; i < num_attributes; i++) {
359 if (data[i * 2] == attribute) {
360 *value = data[(i * 2) + 1];
361 break;
362 }
363 }
364
365 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
366 {
367 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable);
368
369 if (pdraw != NULL && !pdraw->textureTarget)
370 pdraw->textureTarget =
371 determineTextureTarget((const int *) data, num_attributes);
372 if (pdraw != NULL && !pdraw->textureFormat)
373 pdraw->textureFormat =
374 determineTextureFormat((const int *) data, num_attributes);
375 }
376 #endif
377
378 free(data);
379 }
380 }
381
382 UnlockDisplay(dpy);
383 SyncHandle();
384
385 return 0;
386 }
387
388 static void
389 protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode)
390 {
391 xGLXDestroyPbufferReq *req;
392 CARD8 opcode;
393
394 opcode = __glXSetupForCommand(dpy);
395 if (!opcode)
396 return;
397
398 LockDisplay(dpy);
399
400 GetReq(GLXDestroyPbuffer, req);
401 req->reqType = opcode;
402 req->glxCode = glxCode;
403 req->pbuffer = (GLXPbuffer) drawable;
404
405 UnlockDisplay(dpy);
406 SyncHandle();
407 }
408
409 /**
410 * Create a non-pbuffer GLX drawable.
411 */
412 static GLXDrawable
413 CreateDrawable(Display *dpy, struct glx_config *config,
414 Drawable drawable, const int *attrib_list, CARD8 glxCode)
415 {
416 xGLXCreateWindowReq *req;
417 struct glx_drawable *glxDraw;
418 CARD32 *data;
419 unsigned int i;
420 CARD8 opcode;
421 GLXDrawable xid;
422
423 i = 0;
424 if (attrib_list) {
425 while (attrib_list[i * 2] != None)
426 i++;
427 }
428
429 opcode = __glXSetupForCommand(dpy);
430 if (!opcode)
431 return None;
432
433 glxDraw = malloc(sizeof(*glxDraw));
434 if (!glxDraw)
435 return None;
436
437 LockDisplay(dpy);
438 GetReqExtra(GLXCreateWindow, 8 * i, req);
439 data = (CARD32 *) (req + 1);
440
441 req->reqType = opcode;
442 req->glxCode = glxCode;
443 req->screen = config->screen;
444 req->fbconfig = config->fbconfigID;
445 req->window = drawable;
446 req->glxwindow = xid = XAllocID(dpy);
447 req->numAttribs = i;
448
449 if (attrib_list)
450 memcpy(data, attrib_list, 8 * i);
451
452 UnlockDisplay(dpy);
453 SyncHandle();
454
455 if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) {
456 free(glxDraw);
457 return None;
458 }
459
460 if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) {
461 if (glxCode == X_GLXCreatePixmap)
462 glxCode = X_GLXDestroyPixmap;
463 else
464 glxCode = X_GLXDestroyWindow;
465 protocolDestroyDrawable(dpy, xid, glxCode);
466 xid = None;
467 }
468
469 return xid;
470 }
471
472
473 /**
474 * Destroy a non-pbuffer GLX drawable.
475 */
476 static void
477 DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode)
478 {
479 if ((dpy == NULL) || (drawable == 0)) {
480 return;
481 }
482
483 protocolDestroyDrawable(dpy, drawable, glxCode);
484
485 DestroyGLXDrawable(dpy, drawable);
486 DestroyDRIDrawable(dpy, drawable, GL_FALSE);
487
488 return;
489 }
490
491
492 /**
493 * Create a pbuffer.
494 *
495 * This function is used to implement \c glXCreatePbuffer and
496 * \c glXCreateGLXPbufferSGIX.
497 *
498 * \note
499 * This function dynamically determines whether to use the SGIX_pbuffer
500 * version of the protocol or the GLX 1.3 version of the protocol.
501 */
502 static GLXDrawable
503 CreatePbuffer(Display * dpy, struct glx_config *config,
504 unsigned int width, unsigned int height,
505 const int *attrib_list, GLboolean size_in_attribs)
506 {
507 struct glx_display *priv = __glXInitialize(dpy);
508 GLXDrawable id = 0;
509 CARD32 *data;
510 CARD8 opcode;
511 unsigned int i;
512 Pixmap pixmap;
513 GLboolean glx_1_3 = GL_FALSE;
514
515 if (priv == NULL)
516 return None;
517
518 i = 0;
519 if (attrib_list) {
520 while (attrib_list[i * 2])
521 i++;
522 }
523
524 opcode = __glXSetupForCommand(dpy);
525 if (!opcode)
526 return None;
527
528 LockDisplay(dpy);
529 id = XAllocID(dpy);
530
531 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
532 xGLXCreatePbufferReq *req;
533 unsigned int extra = (size_in_attribs) ? 0 : 2;
534
535 glx_1_3 = GL_TRUE;
536
537 GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req);
538 data = (CARD32 *) (req + 1);
539
540 req->reqType = opcode;
541 req->glxCode = X_GLXCreatePbuffer;
542 req->screen = config->screen;
543 req->fbconfig = config->fbconfigID;
544 req->pbuffer = id;
545 req->numAttribs = i + extra;
546
547 if (!size_in_attribs) {
548 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH;
549 data[(2 * i) + 1] = width;
550 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT;
551 data[(2 * i) + 3] = height;
552 data += 4;
553 }
554 }
555 else {
556 xGLXVendorPrivateReq *vpreq;
557
558 GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq);
559 data = (CARD32 *) (vpreq + 1);
560
561 vpreq->reqType = opcode;
562 vpreq->glxCode = X_GLXVendorPrivate;
563 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX;
564
565 data[0] = config->screen;
566 data[1] = config->fbconfigID;
567 data[2] = id;
568 data[3] = width;
569 data[4] = height;
570 data += 5;
571 }
572
573 (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i);
574
575 UnlockDisplay(dpy);
576 SyncHandle();
577
578 pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen),
579 width, height, config->rgbBits);
580
581 if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) {
582 CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX;
583 XFreePixmap(dpy, pixmap);
584 protocolDestroyDrawable(dpy, id, o);
585 id = None;
586 }
587
588 return id;
589 }
590
591 /**
592 * Destroy a pbuffer.
593 *
594 * This function is used to implement \c glXDestroyPbuffer and
595 * \c glXDestroyGLXPbufferSGIX.
596 *
597 * \note
598 * This function dynamically determines whether to use the SGIX_pbuffer
599 * version of the protocol or the GLX 1.3 version of the protocol.
600 */
601 static void
602 DestroyPbuffer(Display * dpy, GLXDrawable drawable)
603 {
604 struct glx_display *priv = __glXInitialize(dpy);
605 CARD8 opcode;
606
607 if ((priv == NULL) || (dpy == NULL) || (drawable == 0)) {
608 return;
609 }
610
611 opcode = __glXSetupForCommand(dpy);
612 if (!opcode)
613 return;
614
615 LockDisplay(dpy);
616
617 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
618 xGLXDestroyPbufferReq *req;
619
620 GetReq(GLXDestroyPbuffer, req);
621 req->reqType = opcode;
622 req->glxCode = X_GLXDestroyPbuffer;
623 req->pbuffer = (GLXPbuffer) drawable;
624 }
625 else {
626 xGLXVendorPrivateWithReplyReq *vpreq;
627 CARD32 *data;
628
629 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq);
630 data = (CARD32 *) (vpreq + 1);
631
632 data[0] = (CARD32) drawable;
633
634 vpreq->reqType = opcode;
635 vpreq->glxCode = X_GLXVendorPrivateWithReply;
636 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX;
637 }
638
639 UnlockDisplay(dpy);
640 SyncHandle();
641
642 DestroyDRIDrawable(dpy, drawable, GL_TRUE);
643
644 return;
645 }
646
647 /**
648 * Create a new pbuffer.
649 */
650 _X_EXPORT GLXPbufferSGIX
651 glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config,
652 unsigned int width, unsigned int height,
653 int *attrib_list)
654 {
655 return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config,
656 width, height,
657 attrib_list, GL_FALSE);
658 }
659
660 #endif /* GLX_USE_APPLEGL */
661
662 /**
663 * Create a new pbuffer.
664 */
665 _X_EXPORT GLXPbuffer
666 glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list)
667 {
668 int i, width, height;
669 #ifdef GLX_USE_APPLEGL
670 GLXPbuffer result;
671 int errorcode;
672 #endif
673
674 width = 0;
675 height = 0;
676
677 WARN_ONCE_GLX_1_3(dpy, __func__);
678
679 #ifdef GLX_USE_APPLEGL
680 for (i = 0; attrib_list[i]; ++i) {
681 switch (attrib_list[i]) {
682 case GLX_PBUFFER_WIDTH:
683 width = attrib_list[i + 1];
684 ++i;
685 break;
686
687 case GLX_PBUFFER_HEIGHT:
688 height = attrib_list[i + 1];
689 ++i;
690 break;
691
692 case GLX_LARGEST_PBUFFER:
693 /* This is a hint we should probably handle, but how? */
694 ++i;
695 break;
696
697 case GLX_PRESERVED_CONTENTS:
698 /* The contents are always preserved with AppleSGLX with CGL. */
699 ++i;
700 break;
701
702 default:
703 return None;
704 }
705 }
706
707 if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode,
708 &result)) {
709 /*
710 * apple_glx_pbuffer_create only sets the errorcode to core X11
711 * errors.
712 */
713 __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true);
714
715 return None;
716 }
717
718 return result;
719 #else
720 for (i = 0; attrib_list[i * 2]; i++) {
721 switch (attrib_list[i * 2]) {
722 case GLX_PBUFFER_WIDTH:
723 width = attrib_list[i * 2 + 1];
724 break;
725 case GLX_PBUFFER_HEIGHT:
726 height = attrib_list[i * 2 + 1];
727 break;
728 }
729 }
730
731 return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config,
732 width, height, attrib_list, GL_TRUE);
733 #endif
734 }
735
736
737 /**
738 * Destroy an existing pbuffer.
739 */
740 _X_EXPORT void
741 glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf)
742 {
743 #ifdef GLX_USE_APPLEGL
744 if (apple_glx_pbuffer_destroy(dpy, pbuf)) {
745 __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false);
746 }
747 #else
748 DestroyPbuffer(dpy, pbuf);
749 #endif
750 }
751
752
753 /**
754 * Query an attribute of a drawable.
755 */
756 _X_EXPORT void
757 glXQueryDrawable(Display * dpy, GLXDrawable drawable,
758 int attribute, unsigned int *value)
759 {
760 WARN_ONCE_GLX_1_3(dpy, __func__);
761 #ifdef GLX_USE_APPLEGL
762 Window root;
763 int x, y;
764 unsigned int width, height, bd, depth;
765
766 if (apple_glx_pixmap_query(drawable, attribute, value))
767 return; /*done */
768
769 if (apple_glx_pbuffer_query(drawable, attribute, value))
770 return; /*done */
771
772 /*
773 * The OpenGL spec states that we should report GLXBadDrawable if
774 * the drawable is invalid, however doing so would require that we
775 * use XSetErrorHandler(), which is known to not be thread safe.
776 * If we use a round-trip call to validate the drawable, there could
777 * be a race, so instead we just opt in favor of letting the
778 * XGetGeometry request fail with a GetGeometry request X error
779 * rather than GLXBadDrawable, in what is hoped to be a rare
780 * case of an invalid drawable. In practice most and possibly all
781 * X11 apps using GLX shouldn't notice a difference.
782 */
783 if (XGetGeometry
784 (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) {
785 switch (attribute) {
786 case GLX_WIDTH:
787 *value = width;
788 break;
789
790 case GLX_HEIGHT:
791 *value = height;
792 break;
793 }
794 }
795 #else
796 GetDrawableAttribute(dpy, drawable, attribute, value);
797 #endif
798 }
799
800
801 #ifndef GLX_USE_APPLEGL
802 /**
803 * Query an attribute of a pbuffer.
804 */
805 _X_EXPORT int
806 glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable,
807 int attribute, unsigned int *value)
808 {
809 return GetDrawableAttribute(dpy, drawable, attribute, value);
810 }
811 #endif
812
813 /**
814 * Select the event mask for a drawable.
815 */
816 _X_EXPORT void
817 glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask)
818 {
819 #ifdef GLX_USE_APPLEGL
820 XWindowAttributes xwattr;
821
822 if (apple_glx_pbuffer_set_event_mask(drawable, mask))
823 return; /*done */
824
825 /*
826 * The spec allows a window, but currently there are no valid
827 * events for a window, so do nothing.
828 */
829 if (XGetWindowAttributes(dpy, drawable, &xwattr))
830 return; /*done */
831 /* The drawable seems to be invalid. Report an error. */
832
833 __glXSendError(dpy, GLXBadDrawable, drawable,
834 X_GLXChangeDrawableAttributes, false);
835 #else
836 CARD32 attribs[2];
837
838 attribs[0] = (CARD32) GLX_EVENT_MASK;
839 attribs[1] = (CARD32) mask;
840
841 ChangeDrawableAttribute(dpy, drawable, attribs, 1);
842 #endif
843 }
844
845
846 /**
847 * Get the selected event mask for a drawable.
848 */
849 _X_EXPORT void
850 glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask)
851 {
852 #ifdef GLX_USE_APPLEGL
853 XWindowAttributes xwattr;
854
855 if (apple_glx_pbuffer_get_event_mask(drawable, mask))
856 return; /*done */
857
858 /*
859 * The spec allows a window, but currently there are no valid
860 * events for a window, so do nothing, but set the mask to 0.
861 */
862 if (XGetWindowAttributes(dpy, drawable, &xwattr)) {
863 /* The window is valid, so set the mask to 0. */
864 *mask = 0;
865 return; /*done */
866 }
867 /* The drawable seems to be invalid. Report an error. */
868
869 __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes,
870 true);
871 #else
872 unsigned int value;
873
874
875 /* The non-sense with value is required because on LP64 platforms
876 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian
877 * we could just type-cast the pointer, but why?
878 */
879
880 GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value);
881 *mask = value;
882 #endif
883 }
884
885
886 _X_EXPORT GLXPixmap
887 glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap,
888 const int *attrib_list)
889 {
890 WARN_ONCE_GLX_1_3(dpy, __func__);
891
892 #ifdef GLX_USE_APPLEGL
893 const struct glx_config *modes = (const struct glx_config *) config;
894
895 if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes))
896 return None;
897
898 return pixmap;
899 #else
900 return CreateDrawable(dpy, (struct glx_config *) config,
901 (Drawable) pixmap, attrib_list, X_GLXCreatePixmap);
902 #endif
903 }
904
905
906 _X_EXPORT GLXWindow
907 glXCreateWindow(Display * dpy, GLXFBConfig config, Window win,
908 const int *attrib_list)
909 {
910 WARN_ONCE_GLX_1_3(dpy, __func__);
911 #ifdef GLX_USE_APPLEGL
912 XWindowAttributes xwattr;
913 XVisualInfo *visinfo;
914
915 (void) attrib_list; /*unused according to GLX 1.4 */
916
917 XGetWindowAttributes(dpy, win, &xwattr);
918
919 visinfo = glXGetVisualFromFBConfig(dpy, config);
920
921 if (NULL == visinfo) {
922 __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false);
923 return None;
924 }
925
926 if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) {
927 __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true);
928 return None;
929 }
930
931 free(visinfo);
932
933 return win;
934 #else
935 return CreateDrawable(dpy, (struct glx_config *) config,
936 (Drawable) win, attrib_list, X_GLXCreateWindow);
937 #endif
938 }
939
940
941 _X_EXPORT void
942 glXDestroyPixmap(Display * dpy, GLXPixmap pixmap)
943 {
944 WARN_ONCE_GLX_1_3(dpy, __func__);
945 #ifdef GLX_USE_APPLEGL
946 if (apple_glx_pixmap_destroy(dpy, pixmap))
947 __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false);
948 #else
949 DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap);
950 #endif
951 }
952
953
954 _X_EXPORT void
955 glXDestroyWindow(Display * dpy, GLXWindow win)
956 {
957 WARN_ONCE_GLX_1_3(dpy, __func__);
958 #ifndef GLX_USE_APPLEGL
959 DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow);
960 #endif
961 }
962
963 #ifndef GLX_USE_APPLEGL
964 _X_EXPORT
965 GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX,
966 (Display * dpy, GLXPbufferSGIX pbuf),
967 (dpy, pbuf), glXDestroyPbuffer)
968
969 _X_EXPORT
970 GLX_ALIAS_VOID(glXSelectEventSGIX,
971 (Display * dpy, GLXDrawable drawable,
972 unsigned long mask), (dpy, drawable, mask), glXSelectEvent)
973
974 _X_EXPORT
975 GLX_ALIAS_VOID(glXGetSelectedEventSGIX,
976 (Display * dpy, GLXDrawable drawable,
977 unsigned long *mask), (dpy, drawable, mask),
978 glXGetSelectedEvent)
979 #endif