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