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