glx_pbuffer.c revision e27913f805acbb7d00f83ba625a8605576738a13
1/* 2 * (C) Copyright IBM Corporation 2004 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file glx_pbuffer.c 27 * Implementation of pbuffer related functions. 28 * 29 * \author Ian Romanick <idr@us.ibm.com> 30 */ 31 32#include <inttypes.h> 33#include "glxclient.h" 34#include <X11/extensions/extutil.h> 35#include <X11/extensions/Xext.h> 36#include <assert.h> 37#include <string.h> 38#include "glxextensions.h" 39 40#ifdef GLX_USE_APPLEGL 41#include <pthread.h> 42#include "apple_glx_drawable.h" 43#include "glx_error.h" 44#endif 45 46#define WARN_ONCE_GLX_1_3(a, b) { \ 47 static int warned=1; \ 48 if(warned) { \ 49 warn_GLX_1_3((a), b ); \ 50 warned=0; \ 51 } \ 52 } 53 54/** 55 * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems. 56 */ 57static void 58warn_GLX_1_3(Display * dpy, const char *function_name) 59{ 60 struct glx_display *priv = __glXInitialize(dpy); 61 62 if (priv->minorVersion < 3) { 63 fprintf(stderr, 64 "WARNING: Application calling GLX 1.3 function \"%s\" " 65 "when GLX 1.3 is not supported! This is an application bug!\n", 66 function_name); 67 } 68} 69 70#ifndef GLX_USE_APPLEGL 71/** 72 * Change a drawable's attribute. 73 * 74 * This function is used to implement \c glXSelectEvent and 75 * \c glXSelectEventSGIX. 76 * 77 * \note 78 * This function dynamically determines whether to use the SGIX_pbuffer 79 * version of the protocol or the GLX 1.3 version of the protocol. 80 * 81 * \todo 82 * This function needs to be modified to work with direct-rendering drivers. 83 */ 84static void 85ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, 86 const CARD32 * attribs, size_t num_attribs) 87{ 88 struct glx_display *priv = __glXInitialize(dpy); 89#ifdef GLX_DIRECT_RENDERING 90 __GLXDRIdrawable *pdraw; 91#endif 92 CARD32 *output; 93 CARD8 opcode; 94 int i; 95 96 if ((dpy == NULL) || (drawable == 0)) { 97 return; 98 } 99 100 opcode = __glXSetupForCommand(dpy); 101 if (!opcode) 102 return; 103 104 LockDisplay(dpy); 105 106 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 107 xGLXChangeDrawableAttributesReq *req; 108 109 GetReqExtra(GLXChangeDrawableAttributes, 8 * 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, 8 + (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[1] = num_attribs; 129 output += 2; 130 } 131 132 (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); 133 134 UnlockDisplay(dpy); 135 SyncHandle(); 136 137#ifdef GLX_DIRECT_RENDERING 138 pdraw = GetGLXDRIDrawable(dpy, drawable); 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 * 266 * \todo 267 * This function needs to be modified to work with direct-rendering drivers. 268 */ 269static int 270GetDrawableAttribute(Display * dpy, GLXDrawable drawable, 271 int attribute, unsigned int *value) 272{ 273 struct glx_display *priv; 274 xGLXGetDrawableAttributesReply reply; 275 CARD32 *data; 276 CARD8 opcode; 277 unsigned int length; 278 unsigned int i; 279 unsigned int num_attributes; 280 GLboolean use_glx_1_3; 281 282 if ((dpy == NULL) || (drawable == 0)) { 283 return 0; 284 } 285 286 priv = __glXInitialize(dpy); 287 use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3)); 288 289 *value = 0; 290 291 292 opcode = __glXSetupForCommand(dpy); 293 if (!opcode) 294 return 0; 295 296 LockDisplay(dpy); 297 298 if (use_glx_1_3) { 299 xGLXGetDrawableAttributesReq *req; 300 301 GetReq(GLXGetDrawableAttributes, req); 302 req->reqType = opcode; 303 req->glxCode = X_GLXGetDrawableAttributes; 304 req->drawable = drawable; 305 } 306 else { 307 xGLXVendorPrivateWithReplyReq *vpreq; 308 309 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq); 310 data = (CARD32 *) (vpreq + 1); 311 data[0] = (CARD32) drawable; 312 313 vpreq->reqType = opcode; 314 vpreq->glxCode = X_GLXVendorPrivateWithReply; 315 vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX; 316 } 317 318 _XReply(dpy, (xReply *) & reply, 0, False); 319 320 if (reply.type == X_Error) { 321 UnlockDisplay(dpy); 322 SyncHandle(); 323 return 0; 324 } 325 326 length = reply.length; 327 if (length) { 328 num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2; 329 data = (CARD32 *) Xmalloc(length * sizeof(CARD32)); 330 if (data == NULL) { 331 /* Throw data on the floor */ 332 _XEatData(dpy, length); 333 } 334 else { 335 _XRead(dpy, (char *) data, length * sizeof(CARD32)); 336 337 /* Search the set of returned attributes for the attribute requested by 338 * the caller. 339 */ 340 for (i = 0; i < num_attributes; i++) { 341 if (data[i * 2] == attribute) { 342 *value = data[(i * 2) + 1]; 343 break; 344 } 345 } 346 347#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) 348 { 349 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 350 351 if (pdraw != NULL && !pdraw->textureTarget) 352 pdraw->textureTarget = 353 determineTextureTarget((const int *) data, num_attributes); 354 if (pdraw != NULL && !pdraw->textureFormat) 355 pdraw->textureFormat = 356 determineTextureFormat((const int *) data, num_attributes); 357 } 358#endif 359 360 Xfree(data); 361 } 362 } 363 364 UnlockDisplay(dpy); 365 SyncHandle(); 366 367 return 0; 368} 369 370/** 371 * Create a non-pbuffer GLX drawable. 372 * 373 * \todo 374 * This function needs to be modified to work with direct-rendering drivers. 375 */ 376static GLXDrawable 377CreateDrawable(Display *dpy, struct glx_config *config, 378 Drawable drawable, const int *attrib_list, CARD8 glxCode) 379{ 380 xGLXCreateWindowReq *req; 381 CARD32 *data; 382 unsigned int i; 383 CARD8 opcode; 384 385 i = 0; 386 if (attrib_list) { 387 while (attrib_list[i * 2] != None) 388 i++; 389 } 390 391 opcode = __glXSetupForCommand(dpy); 392 if (!opcode) 393 return None; 394 395 LockDisplay(dpy); 396 GetReqExtra(GLXCreateWindow, 8 * i, req); 397 data = (CARD32 *) (req + 1); 398 399 req->reqType = opcode; 400 req->glxCode = glxCode; 401 req->screen = config->screen; 402 req->fbconfig = config->fbconfigID; 403 req->window = drawable; 404 req->glxwindow = XAllocID(dpy); 405 req->numAttribs = i; 406 407 if (attrib_list) 408 memcpy(data, attrib_list, 8 * i); 409 410 UnlockDisplay(dpy); 411 SyncHandle(); 412 413 CreateDRIDrawable(dpy, config, drawable, req->glxwindow, attrib_list, i); 414 415 return req->glxwindow; 416} 417 418 419/** 420 * Destroy a non-pbuffer GLX drawable. 421 */ 422static void 423DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) 424{ 425 xGLXDestroyPbufferReq *req; 426 CARD8 opcode; 427 428 if ((dpy == NULL) || (drawable == 0)) { 429 return; 430 } 431 432 433 opcode = __glXSetupForCommand(dpy); 434 if (!opcode) 435 return; 436 437 LockDisplay(dpy); 438 439 GetReq(GLXDestroyPbuffer, req); 440 req->reqType = opcode; 441 req->glxCode = glxCode; 442 req->pbuffer = (GLXPbuffer) drawable; 443 444 UnlockDisplay(dpy); 445 SyncHandle(); 446 447 DestroyDRIDrawable(dpy, drawable, GL_FALSE); 448 449 return; 450} 451 452 453/** 454 * Create a pbuffer. 455 * 456 * This function is used to implement \c glXCreatePbuffer and 457 * \c glXCreateGLXPbufferSGIX. 458 * 459 * \note 460 * This function dynamically determines whether to use the SGIX_pbuffer 461 * version of the protocol or the GLX 1.3 version of the protocol. 462 * 463 * \todo 464 * This function needs to be modified to work with direct-rendering drivers. 465 */ 466static GLXDrawable 467CreatePbuffer(Display * dpy, struct glx_config *config, 468 unsigned int width, unsigned int height, 469 const int *attrib_list, GLboolean size_in_attribs) 470{ 471 struct glx_display *priv = __glXInitialize(dpy); 472 GLXDrawable id = 0; 473 CARD32 *data; 474 CARD8 opcode; 475 unsigned int i; 476 Pixmap pixmap; 477 478 i = 0; 479 if (attrib_list) { 480 while (attrib_list[i * 2]) 481 i++; 482 } 483 484 opcode = __glXSetupForCommand(dpy); 485 if (!opcode) 486 return None; 487 488 LockDisplay(dpy); 489 id = XAllocID(dpy); 490 491 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 492 xGLXCreatePbufferReq *req; 493 unsigned int extra = (size_in_attribs) ? 0 : 2; 494 495 GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req); 496 data = (CARD32 *) (req + 1); 497 498 req->reqType = opcode; 499 req->glxCode = X_GLXCreatePbuffer; 500 req->screen = config->screen; 501 req->fbconfig = config->fbconfigID; 502 req->pbuffer = id; 503 req->numAttribs = i + extra; 504 505 if (!size_in_attribs) { 506 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH; 507 data[(2 * i) + 1] = width; 508 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT; 509 data[(2 * i) + 3] = height; 510 data += 4; 511 } 512 } 513 else { 514 xGLXVendorPrivateReq *vpreq; 515 516 GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq); 517 data = (CARD32 *) (vpreq + 1); 518 519 vpreq->reqType = opcode; 520 vpreq->glxCode = X_GLXVendorPrivate; 521 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX; 522 523 data[0] = config->screen; 524 data[1] = config->fbconfigID; 525 data[2] = id; 526 data[3] = width; 527 data[4] = height; 528 data += 5; 529 } 530 531 (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i); 532 533 UnlockDisplay(dpy); 534 SyncHandle(); 535 536 pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen), 537 width, height, config->rgbBits); 538 539 CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i); 540 541 return id; 542} 543 544/** 545 * Destroy a pbuffer. 546 * 547 * This function is used to implement \c glXDestroyPbuffer and 548 * \c glXDestroyGLXPbufferSGIX. 549 * 550 * \note 551 * This function dynamically determines whether to use the SGIX_pbuffer 552 * version of the protocol or the GLX 1.3 version of the protocol. 553 */ 554static void 555DestroyPbuffer(Display * dpy, GLXDrawable drawable) 556{ 557 struct glx_display *priv = __glXInitialize(dpy); 558 CARD8 opcode; 559 560 if ((dpy == NULL) || (drawable == 0)) { 561 return; 562 } 563 564 opcode = __glXSetupForCommand(dpy); 565 if (!opcode) 566 return; 567 568 LockDisplay(dpy); 569 570 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 571 xGLXDestroyPbufferReq *req; 572 573 GetReq(GLXDestroyPbuffer, req); 574 req->reqType = opcode; 575 req->glxCode = X_GLXDestroyPbuffer; 576 req->pbuffer = (GLXPbuffer) drawable; 577 } 578 else { 579 xGLXVendorPrivateWithReplyReq *vpreq; 580 CARD32 *data; 581 582 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq); 583 data = (CARD32 *) (vpreq + 1); 584 585 data[0] = (CARD32) drawable; 586 587 vpreq->reqType = opcode; 588 vpreq->glxCode = X_GLXVendorPrivateWithReply; 589 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX; 590 } 591 592 UnlockDisplay(dpy); 593 SyncHandle(); 594 595 DestroyDRIDrawable(dpy, drawable, GL_TRUE); 596 597 return; 598} 599 600/** 601 * Create a new pbuffer. 602 */ 603_X_EXPORT GLXPbufferSGIX 604glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, 605 unsigned int width, unsigned int height, 606 int *attrib_list) 607{ 608 return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config, 609 width, height, 610 attrib_list, GL_FALSE); 611} 612 613#endif /* GLX_USE_APPLEGL */ 614 615/** 616 * Create a new pbuffer. 617 */ 618_X_EXPORT GLXPbuffer 619glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) 620{ 621 int i, width, height; 622#ifdef GLX_USE_APPLEGL 623 GLXPbuffer result; 624 int errorcode; 625#endif 626 627 width = 0; 628 height = 0; 629 630 WARN_ONCE_GLX_1_3(dpy, __func__); 631 632#ifdef GLX_USE_APPLEGL 633 for (i = 0; attrib_list[i]; ++i) { 634 switch (attrib_list[i]) { 635 case GLX_PBUFFER_WIDTH: 636 width = attrib_list[i + 1]; 637 ++i; 638 break; 639 640 case GLX_PBUFFER_HEIGHT: 641 height = attrib_list[i + 1]; 642 ++i; 643 break; 644 645 case GLX_LARGEST_PBUFFER: 646 /* This is a hint we should probably handle, but how? */ 647 ++i; 648 break; 649 650 case GLX_PRESERVED_CONTENTS: 651 /* The contents are always preserved with AppleSGLX with CGL. */ 652 ++i; 653 break; 654 655 default: 656 return None; 657 } 658 } 659 660 if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode, 661 &result)) { 662 /* 663 * apple_glx_pbuffer_create only sets the errorcode to core X11 664 * errors. 665 */ 666 __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true); 667 668 return None; 669 } 670 671 return result; 672#else 673 for (i = 0; attrib_list[i * 2]; i++) { 674 switch (attrib_list[i * 2]) { 675 case GLX_PBUFFER_WIDTH: 676 width = attrib_list[i * 2 + 1]; 677 break; 678 case GLX_PBUFFER_HEIGHT: 679 height = attrib_list[i * 2 + 1]; 680 break; 681 } 682 } 683 684 return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config, 685 width, height, attrib_list, GL_TRUE); 686#endif 687} 688 689 690/** 691 * Destroy an existing pbuffer. 692 */ 693_X_EXPORT void 694glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf) 695{ 696#ifdef GLX_USE_APPLEGL 697 if (apple_glx_pbuffer_destroy(dpy, pbuf)) { 698 __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false); 699 } 700#else 701 DestroyPbuffer(dpy, pbuf); 702#endif 703} 704 705 706/** 707 * Query an attribute of a drawable. 708 */ 709_X_EXPORT void 710glXQueryDrawable(Display * dpy, GLXDrawable drawable, 711 int attribute, unsigned int *value) 712{ 713 WARN_ONCE_GLX_1_3(dpy, __func__); 714#ifdef GLX_USE_APPLEGL 715 Window root; 716 int x, y; 717 unsigned int width, height, bd, depth; 718 719 if (apple_glx_pixmap_query(drawable, attribute, value)) 720 return; /*done */ 721 722 if (apple_glx_pbuffer_query(drawable, attribute, value)) 723 return; /*done */ 724 725 /* 726 * The OpenGL spec states that we should report GLXBadDrawable if 727 * the drawable is invalid, however doing so would require that we 728 * use XSetErrorHandler(), which is known to not be thread safe. 729 * If we use a round-trip call to validate the drawable, there could 730 * be a race, so instead we just opt in favor of letting the 731 * XGetGeometry request fail with a GetGeometry request X error 732 * rather than GLXBadDrawable, in what is hoped to be a rare 733 * case of an invalid drawable. In practice most and possibly all 734 * X11 apps using GLX shouldn't notice a difference. 735 */ 736 if (XGetGeometry 737 (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) { 738 switch (attribute) { 739 case GLX_WIDTH: 740 *value = width; 741 break; 742 743 case GLX_HEIGHT: 744 *value = height; 745 break; 746 } 747 } 748#else 749 GetDrawableAttribute(dpy, drawable, attribute, value); 750#endif 751} 752 753 754#ifndef GLX_USE_APPLEGL 755/** 756 * Query an attribute of a pbuffer. 757 */ 758_X_EXPORT int 759glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable, 760 int attribute, unsigned int *value) 761{ 762 return GetDrawableAttribute(dpy, drawable, attribute, value); 763} 764#endif 765 766/** 767 * Select the event mask for a drawable. 768 */ 769_X_EXPORT void 770glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask) 771{ 772#ifdef GLX_USE_APPLEGL 773 XWindowAttributes xwattr; 774 775 if (apple_glx_pbuffer_set_event_mask(drawable, mask)) 776 return; /*done */ 777 778 /* 779 * The spec allows a window, but currently there are no valid 780 * events for a window, so do nothing. 781 */ 782 if (XGetWindowAttributes(dpy, drawable, &xwattr)) 783 return; /*done */ 784 /* The drawable seems to be invalid. Report an error. */ 785 786 __glXSendError(dpy, GLXBadDrawable, drawable, 787 X_GLXChangeDrawableAttributes, false); 788#else 789 CARD32 attribs[2]; 790 791 attribs[0] = (CARD32) GLX_EVENT_MASK; 792 attribs[1] = (CARD32) mask; 793 794 ChangeDrawableAttribute(dpy, drawable, attribs, 1); 795#endif 796} 797 798 799/** 800 * Get the selected event mask for a drawable. 801 */ 802_X_EXPORT void 803glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) 804{ 805#ifdef GLX_USE_APPLEGL 806 XWindowAttributes xwattr; 807 808 if (apple_glx_pbuffer_get_event_mask(drawable, mask)) 809 return; /*done */ 810 811 /* 812 * The spec allows a window, but currently there are no valid 813 * events for a window, so do nothing, but set the mask to 0. 814 */ 815 if (XGetWindowAttributes(dpy, drawable, &xwattr)) { 816 /* The window is valid, so set the mask to 0. */ 817 *mask = 0; 818 return; /*done */ 819 } 820 /* The drawable seems to be invalid. Report an error. */ 821 822 __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes, 823 true); 824#else 825 unsigned int value; 826 827 828 /* The non-sense with value is required because on LP64 platforms 829 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian 830 * we could just type-cast the pointer, but why? 831 */ 832 833 GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); 834 *mask = value; 835#endif 836} 837 838 839_X_EXPORT GLXPixmap 840glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, 841 const int *attrib_list) 842{ 843 WARN_ONCE_GLX_1_3(dpy, __func__); 844 845#ifdef GLX_USE_APPLEGL 846 const struct glx_config *modes = (const __GLcontextModes *) config; 847 848 if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes)) 849 return None; 850 851 return pixmap; 852#else 853 return CreateDrawable(dpy, (struct glx_config *) config, 854 (Drawable) pixmap, attrib_list, X_GLXCreatePixmap); 855#endif 856} 857 858 859_X_EXPORT GLXWindow 860glXCreateWindow(Display * dpy, GLXFBConfig config, Window win, 861 const int *attrib_list) 862{ 863 WARN_ONCE_GLX_1_3(dpy, __func__); 864#ifdef GLX_USE_APPLEGL 865 XWindowAttributes xwattr; 866 XVisualInfo *visinfo; 867 868 (void) attrib_list; /*unused according to GLX 1.4 */ 869 870 XGetWindowAttributes(dpy, win, &xwattr); 871 872 visinfo = glXGetVisualFromFBConfig(dpy, config); 873 874 if (NULL == visinfo) { 875 __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false); 876 return None; 877 } 878 879 if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) { 880 __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true); 881 return None; 882 } 883 884 XFree(visinfo); 885 886 return win; 887#else 888 return CreateDrawable(dpy, (struct glx_config *) config, 889 (Drawable) win, attrib_list, X_GLXCreateWindow); 890#endif 891} 892 893 894_X_EXPORT void 895glXDestroyPixmap(Display * dpy, GLXPixmap pixmap) 896{ 897 WARN_ONCE_GLX_1_3(dpy, __func__); 898#ifdef GLX_USE_APPLEGL 899 if (apple_glx_pixmap_destroy(dpy, pixmap)) 900 __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false); 901#else 902 DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap); 903#endif 904} 905 906 907_X_EXPORT void 908glXDestroyWindow(Display * dpy, GLXWindow win) 909{ 910 WARN_ONCE_GLX_1_3(dpy, __func__); 911#ifndef GLX_USE_APPLEGL 912 DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow); 913#endif 914} 915 916#ifndef GLX_USE_APPLEGL 917_X_EXPORT 918GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX, 919 (Display * dpy, GLXPbufferSGIX pbuf), 920 (dpy, pbuf), glXDestroyPbuffer) 921 922_X_EXPORT 923GLX_ALIAS_VOID(glXSelectEventSGIX, 924 (Display * dpy, GLXDrawable drawable, 925 unsigned long mask), (dpy, drawable, mask), glXSelectEvent) 926 927_X_EXPORT 928GLX_ALIAS_VOID(glXGetSelectedEventSGIX, 929 (Display * dpy, GLXDrawable drawable, 930 unsigned long *mask), (dpy, drawable, mask), 931 glXGetSelectedEvent) 932#endif 933