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