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