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