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