glx_pbuffer.c revision 4833104718677caad0027d5e7539ca9bba389392
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 */ 81static void 82ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, 83 const CARD32 * attribs, size_t num_attribs) 84{ 85 struct glx_display *priv = __glXInitialize(dpy); 86#ifdef GLX_DIRECT_RENDERING 87 __GLXDRIdrawable *pdraw; 88#endif 89 CARD32 *output; 90 CARD8 opcode; 91 int i; 92 93 if ((dpy == NULL) || (drawable == 0)) { 94 return; 95 } 96 97 opcode = __glXSetupForCommand(dpy); 98 if (!opcode) 99 return; 100 101 LockDisplay(dpy); 102 103 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 104 xGLXChangeDrawableAttributesReq *req; 105 106 GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req); 107 output = (CARD32 *) (req + 1); 108 109 req->reqType = opcode; 110 req->glxCode = X_GLXChangeDrawableAttributes; 111 req->drawable = drawable; 112 req->numAttribs = (CARD32) num_attribs; 113 } 114 else { 115 xGLXVendorPrivateWithReplyReq *vpreq; 116 117 GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq); 118 output = (CARD32 *) (vpreq + 1); 119 120 vpreq->reqType = opcode; 121 vpreq->glxCode = X_GLXVendorPrivateWithReply; 122 vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX; 123 124 output[0] = (CARD32) drawable; 125 output[1] = num_attribs; 126 output += 2; 127 } 128 129 (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); 130 131 UnlockDisplay(dpy); 132 SyncHandle(); 133 134#ifdef GLX_DIRECT_RENDERING 135 pdraw = GetGLXDRIDrawable(dpy, drawable); 136 137 if (!pdraw) 138 return; 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 GLboolean 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 GL_TRUE; 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 GL_FALSE; 208 } 209 210 if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) { 211 (*pdraw->destroyDrawable) (pdraw); 212 return GL_FALSE; 213 } 214 215 pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs); 216 pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs); 217 218 return GL_TRUE; 219} 220 221static void 222DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) 223{ 224 struct glx_display *const priv = __glXInitialize(dpy); 225 __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); 226 XID xid; 227 228 if (pdraw != NULL) { 229 xid = pdraw->xDrawable; 230 (*pdraw->destroyDrawable) (pdraw); 231 __glxHashDelete(priv->drawHash, drawable); 232 if (destroy_xdrawable) 233 XFreePixmap(priv->dpy, xid); 234 } 235} 236 237#else 238 239static GLboolean 240CreateDRIDrawable(Display *dpy, const struct glx_config * fbconfig, 241 XID drawable, XID glxdrawable, 242 const int *attrib_list, size_t num_attribs) 243{ 244 return GL_FALSE; 245} 246 247static void 248DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) 249{ 250} 251 252#endif 253 254/** 255 * Get a drawable's attribute. 256 * 257 * This function is used to implement \c glXGetSelectedEvent and 258 * \c glXGetSelectedEventSGIX. 259 * 260 * \note 261 * This function dynamically determines whether to use the SGIX_pbuffer 262 * version of the protocol or the GLX 1.3 version of the protocol. 263 * 264 * \todo 265 * The number of attributes returned is likely to be small, probably less than 266 * 10. Given that, this routine should try to use an array on the stack to 267 * capture the reply rather than always calling Xmalloc. 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 370static void 371protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode) 372{ 373 xGLXDestroyPbufferReq *req; 374 CARD8 opcode; 375 376 opcode = __glXSetupForCommand(dpy); 377 if (!opcode) 378 return; 379 380 LockDisplay(dpy); 381 382 GetReq(GLXDestroyPbuffer, req); 383 req->reqType = opcode; 384 req->glxCode = glxCode; 385 req->pbuffer = (GLXPbuffer) drawable; 386 387 UnlockDisplay(dpy); 388 SyncHandle(); 389} 390 391/** 392 * Create a non-pbuffer GLX drawable. 393 */ 394static GLXDrawable 395CreateDrawable(Display *dpy, struct glx_config *config, 396 Drawable drawable, const int *attrib_list, CARD8 glxCode) 397{ 398 xGLXCreateWindowReq *req; 399 CARD32 *data; 400 unsigned int i; 401 CARD8 opcode; 402 GLXDrawable xid; 403 404 i = 0; 405 if (attrib_list) { 406 while (attrib_list[i * 2] != None) 407 i++; 408 } 409 410 opcode = __glXSetupForCommand(dpy); 411 if (!opcode) 412 return None; 413 414 LockDisplay(dpy); 415 GetReqExtra(GLXCreateWindow, 8 * i, req); 416 data = (CARD32 *) (req + 1); 417 418 req->reqType = opcode; 419 req->glxCode = glxCode; 420 req->screen = config->screen; 421 req->fbconfig = config->fbconfigID; 422 req->window = drawable; 423 req->glxwindow = xid = XAllocID(dpy); 424 req->numAttribs = i; 425 426 if (attrib_list) 427 memcpy(data, attrib_list, 8 * i); 428 429 UnlockDisplay(dpy); 430 SyncHandle(); 431 432 if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) { 433 if (glxCode == X_GLXCreatePixmap) 434 glxCode = X_GLXDestroyPixmap; 435 else 436 glxCode = X_GLXDestroyWindow; 437 protocolDestroyDrawable(dpy, xid, glxCode); 438 xid = None; 439 } 440 441 return xid; 442} 443 444 445/** 446 * Destroy a non-pbuffer GLX drawable. 447 */ 448static void 449DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) 450{ 451 if ((dpy == NULL) || (drawable == 0)) { 452 return; 453 } 454 455 protocolDestroyDrawable(dpy, drawable, glxCode); 456 457 DestroyDRIDrawable(dpy, drawable, GL_FALSE); 458 459 return; 460} 461 462 463/** 464 * Create a pbuffer. 465 * 466 * This function is used to implement \c glXCreatePbuffer and 467 * \c glXCreateGLXPbufferSGIX. 468 * 469 * \note 470 * This function dynamically determines whether to use the SGIX_pbuffer 471 * version of the protocol or the GLX 1.3 version of the protocol. 472 */ 473static GLXDrawable 474CreatePbuffer(Display * dpy, struct glx_config *config, 475 unsigned int width, unsigned int height, 476 const int *attrib_list, GLboolean size_in_attribs) 477{ 478 struct glx_display *priv = __glXInitialize(dpy); 479 GLXDrawable id = 0; 480 CARD32 *data; 481 CARD8 opcode; 482 unsigned int i; 483 Pixmap pixmap; 484 GLboolean glx_1_3 = GL_FALSE; 485 486 i = 0; 487 if (attrib_list) { 488 while (attrib_list[i * 2]) 489 i++; 490 } 491 492 opcode = __glXSetupForCommand(dpy); 493 if (!opcode) 494 return None; 495 496 LockDisplay(dpy); 497 id = XAllocID(dpy); 498 499 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 500 xGLXCreatePbufferReq *req; 501 unsigned int extra = (size_in_attribs) ? 0 : 2; 502 503 glx_1_3 = GL_TRUE; 504 505 GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req); 506 data = (CARD32 *) (req + 1); 507 508 req->reqType = opcode; 509 req->glxCode = X_GLXCreatePbuffer; 510 req->screen = config->screen; 511 req->fbconfig = config->fbconfigID; 512 req->pbuffer = id; 513 req->numAttribs = i + extra; 514 515 if (!size_in_attribs) { 516 data[(2 * i) + 0] = GLX_PBUFFER_WIDTH; 517 data[(2 * i) + 1] = width; 518 data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT; 519 data[(2 * i) + 3] = height; 520 data += 4; 521 } 522 } 523 else { 524 xGLXVendorPrivateReq *vpreq; 525 526 GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq); 527 data = (CARD32 *) (vpreq + 1); 528 529 vpreq->reqType = opcode; 530 vpreq->glxCode = X_GLXVendorPrivate; 531 vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX; 532 533 data[0] = config->screen; 534 data[1] = config->fbconfigID; 535 data[2] = id; 536 data[3] = width; 537 data[4] = height; 538 data += 5; 539 } 540 541 (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i); 542 543 UnlockDisplay(dpy); 544 SyncHandle(); 545 546 pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen), 547 width, height, config->rgbBits); 548 549 if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) { 550 CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX; 551 XFreePixmap(dpy, pixmap); 552 protocolDestroyDrawable(dpy, id, o); 553 id = None; 554 } 555 556 return id; 557} 558 559/** 560 * Destroy a pbuffer. 561 * 562 * This function is used to implement \c glXDestroyPbuffer and 563 * \c glXDestroyGLXPbufferSGIX. 564 * 565 * \note 566 * This function dynamically determines whether to use the SGIX_pbuffer 567 * version of the protocol or the GLX 1.3 version of the protocol. 568 */ 569static void 570DestroyPbuffer(Display * dpy, GLXDrawable drawable) 571{ 572 struct glx_display *priv = __glXInitialize(dpy); 573 CARD8 opcode; 574 575 if ((dpy == NULL) || (drawable == 0)) { 576 return; 577 } 578 579 opcode = __glXSetupForCommand(dpy); 580 if (!opcode) 581 return; 582 583 LockDisplay(dpy); 584 585 if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { 586 xGLXDestroyPbufferReq *req; 587 588 GetReq(GLXDestroyPbuffer, req); 589 req->reqType = opcode; 590 req->glxCode = X_GLXDestroyPbuffer; 591 req->pbuffer = (GLXPbuffer) drawable; 592 } 593 else { 594 xGLXVendorPrivateWithReplyReq *vpreq; 595 CARD32 *data; 596 597 GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq); 598 data = (CARD32 *) (vpreq + 1); 599 600 data[0] = (CARD32) drawable; 601 602 vpreq->reqType = opcode; 603 vpreq->glxCode = X_GLXVendorPrivateWithReply; 604 vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX; 605 } 606 607 UnlockDisplay(dpy); 608 SyncHandle(); 609 610 DestroyDRIDrawable(dpy, drawable, GL_TRUE); 611 612 return; 613} 614 615/** 616 * Create a new pbuffer. 617 */ 618_X_EXPORT GLXPbufferSGIX 619glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, 620 unsigned int width, unsigned int height, 621 int *attrib_list) 622{ 623 return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config, 624 width, height, 625 attrib_list, GL_FALSE); 626} 627 628#endif /* GLX_USE_APPLEGL */ 629 630/** 631 * Create a new pbuffer. 632 */ 633_X_EXPORT GLXPbuffer 634glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) 635{ 636 int i, width, height; 637#ifdef GLX_USE_APPLEGL 638 GLXPbuffer result; 639 int errorcode; 640#endif 641 642 width = 0; 643 height = 0; 644 645 WARN_ONCE_GLX_1_3(dpy, __func__); 646 647#ifdef GLX_USE_APPLEGL 648 for (i = 0; attrib_list[i]; ++i) { 649 switch (attrib_list[i]) { 650 case GLX_PBUFFER_WIDTH: 651 width = attrib_list[i + 1]; 652 ++i; 653 break; 654 655 case GLX_PBUFFER_HEIGHT: 656 height = attrib_list[i + 1]; 657 ++i; 658 break; 659 660 case GLX_LARGEST_PBUFFER: 661 /* This is a hint we should probably handle, but how? */ 662 ++i; 663 break; 664 665 case GLX_PRESERVED_CONTENTS: 666 /* The contents are always preserved with AppleSGLX with CGL. */ 667 ++i; 668 break; 669 670 default: 671 return None; 672 } 673 } 674 675 if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode, 676 &result)) { 677 /* 678 * apple_glx_pbuffer_create only sets the errorcode to core X11 679 * errors. 680 */ 681 __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true); 682 683 return None; 684 } 685 686 return result; 687#else 688 for (i = 0; attrib_list[i * 2]; i++) { 689 switch (attrib_list[i * 2]) { 690 case GLX_PBUFFER_WIDTH: 691 width = attrib_list[i * 2 + 1]; 692 break; 693 case GLX_PBUFFER_HEIGHT: 694 height = attrib_list[i * 2 + 1]; 695 break; 696 } 697 } 698 699 return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config, 700 width, height, attrib_list, GL_TRUE); 701#endif 702} 703 704 705/** 706 * Destroy an existing pbuffer. 707 */ 708_X_EXPORT void 709glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf) 710{ 711#ifdef GLX_USE_APPLEGL 712 if (apple_glx_pbuffer_destroy(dpy, pbuf)) { 713 __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false); 714 } 715#else 716 DestroyPbuffer(dpy, pbuf); 717#endif 718} 719 720 721/** 722 * Query an attribute of a drawable. 723 */ 724_X_EXPORT void 725glXQueryDrawable(Display * dpy, GLXDrawable drawable, 726 int attribute, unsigned int *value) 727{ 728 WARN_ONCE_GLX_1_3(dpy, __func__); 729#ifdef GLX_USE_APPLEGL 730 Window root; 731 int x, y; 732 unsigned int width, height, bd, depth; 733 734 if (apple_glx_pixmap_query(drawable, attribute, value)) 735 return; /*done */ 736 737 if (apple_glx_pbuffer_query(drawable, attribute, value)) 738 return; /*done */ 739 740 /* 741 * The OpenGL spec states that we should report GLXBadDrawable if 742 * the drawable is invalid, however doing so would require that we 743 * use XSetErrorHandler(), which is known to not be thread safe. 744 * If we use a round-trip call to validate the drawable, there could 745 * be a race, so instead we just opt in favor of letting the 746 * XGetGeometry request fail with a GetGeometry request X error 747 * rather than GLXBadDrawable, in what is hoped to be a rare 748 * case of an invalid drawable. In practice most and possibly all 749 * X11 apps using GLX shouldn't notice a difference. 750 */ 751 if (XGetGeometry 752 (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) { 753 switch (attribute) { 754 case GLX_WIDTH: 755 *value = width; 756 break; 757 758 case GLX_HEIGHT: 759 *value = height; 760 break; 761 } 762 } 763#else 764 GetDrawableAttribute(dpy, drawable, attribute, value); 765#endif 766} 767 768 769#ifndef GLX_USE_APPLEGL 770/** 771 * Query an attribute of a pbuffer. 772 */ 773_X_EXPORT int 774glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable, 775 int attribute, unsigned int *value) 776{ 777 return GetDrawableAttribute(dpy, drawable, attribute, value); 778} 779#endif 780 781/** 782 * Select the event mask for a drawable. 783 */ 784_X_EXPORT void 785glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask) 786{ 787#ifdef GLX_USE_APPLEGL 788 XWindowAttributes xwattr; 789 790 if (apple_glx_pbuffer_set_event_mask(drawable, mask)) 791 return; /*done */ 792 793 /* 794 * The spec allows a window, but currently there are no valid 795 * events for a window, so do nothing. 796 */ 797 if (XGetWindowAttributes(dpy, drawable, &xwattr)) 798 return; /*done */ 799 /* The drawable seems to be invalid. Report an error. */ 800 801 __glXSendError(dpy, GLXBadDrawable, drawable, 802 X_GLXChangeDrawableAttributes, false); 803#else 804 CARD32 attribs[2]; 805 806 attribs[0] = (CARD32) GLX_EVENT_MASK; 807 attribs[1] = (CARD32) mask; 808 809 ChangeDrawableAttribute(dpy, drawable, attribs, 1); 810#endif 811} 812 813 814/** 815 * Get the selected event mask for a drawable. 816 */ 817_X_EXPORT void 818glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) 819{ 820#ifdef GLX_USE_APPLEGL 821 XWindowAttributes xwattr; 822 823 if (apple_glx_pbuffer_get_event_mask(drawable, mask)) 824 return; /*done */ 825 826 /* 827 * The spec allows a window, but currently there are no valid 828 * events for a window, so do nothing, but set the mask to 0. 829 */ 830 if (XGetWindowAttributes(dpy, drawable, &xwattr)) { 831 /* The window is valid, so set the mask to 0. */ 832 *mask = 0; 833 return; /*done */ 834 } 835 /* The drawable seems to be invalid. Report an error. */ 836 837 __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes, 838 true); 839#else 840 unsigned int value; 841 842 843 /* The non-sense with value is required because on LP64 platforms 844 * sizeof(unsigned int) != sizeof(unsigned long). On little-endian 845 * we could just type-cast the pointer, but why? 846 */ 847 848 GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); 849 *mask = value; 850#endif 851} 852 853 854_X_EXPORT GLXPixmap 855glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, 856 const int *attrib_list) 857{ 858 WARN_ONCE_GLX_1_3(dpy, __func__); 859 860#ifdef GLX_USE_APPLEGL 861 const struct glx_config *modes = (const struct glx_config *) config; 862 863 if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes)) 864 return None; 865 866 return pixmap; 867#else 868 return CreateDrawable(dpy, (struct glx_config *) config, 869 (Drawable) pixmap, attrib_list, X_GLXCreatePixmap); 870#endif 871} 872 873 874_X_EXPORT GLXWindow 875glXCreateWindow(Display * dpy, GLXFBConfig config, Window win, 876 const int *attrib_list) 877{ 878 WARN_ONCE_GLX_1_3(dpy, __func__); 879#ifdef GLX_USE_APPLEGL 880 XWindowAttributes xwattr; 881 XVisualInfo *visinfo; 882 883 (void) attrib_list; /*unused according to GLX 1.4 */ 884 885 XGetWindowAttributes(dpy, win, &xwattr); 886 887 visinfo = glXGetVisualFromFBConfig(dpy, config); 888 889 if (NULL == visinfo) { 890 __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false); 891 return None; 892 } 893 894 if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) { 895 __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true); 896 return None; 897 } 898 899 XFree(visinfo); 900 901 return win; 902#else 903 return CreateDrawable(dpy, (struct glx_config *) config, 904 (Drawable) win, attrib_list, X_GLXCreateWindow); 905#endif 906} 907 908 909_X_EXPORT void 910glXDestroyPixmap(Display * dpy, GLXPixmap pixmap) 911{ 912 WARN_ONCE_GLX_1_3(dpy, __func__); 913#ifdef GLX_USE_APPLEGL 914 if (apple_glx_pixmap_destroy(dpy, pixmap)) 915 __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false); 916#else 917 DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap); 918#endif 919} 920 921 922_X_EXPORT void 923glXDestroyWindow(Display * dpy, GLXWindow win) 924{ 925 WARN_ONCE_GLX_1_3(dpy, __func__); 926#ifndef GLX_USE_APPLEGL 927 DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow); 928#endif 929} 930 931#ifndef GLX_USE_APPLEGL 932_X_EXPORT 933GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX, 934 (Display * dpy, GLXPbufferSGIX pbuf), 935 (dpy, pbuf), glXDestroyPbuffer) 936 937_X_EXPORT 938GLX_ALIAS_VOID(glXSelectEventSGIX, 939 (Display * dpy, GLXDrawable drawable, 940 unsigned long mask), (dpy, drawable, mask), glXSelectEvent) 941 942_X_EXPORT 943GLX_ALIAS_VOID(glXGetSelectedEventSGIX, 944 (Display * dpy, GLXDrawable drawable, 945 unsigned long *mask), (dpy, drawable, mask), 946 glXGetSelectedEvent) 947#endif 948