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