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