glxcmds.c revision 83cfd353
1/* 2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice including the dates of first publication and 13 * either this permission notice or a reference to 14 * http://oss.sgi.com/projects/FreeB/ 15 * shall be included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Except as contained in this notice, the name of Silicon Graphics, Inc. 26 * shall not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization from 28 * Silicon Graphics, Inc. 29 */ 30 31#ifdef HAVE_DIX_CONFIG_H 32#include <dix-config.h> 33#endif 34 35#include <string.h> 36#include <assert.h> 37 38#include "glxserver.h" 39#include <GL/glxtokens.h> 40#include <unpack.h> 41#include <pixmapstr.h> 42#include <windowstr.h> 43#include "glxutil.h" 44#include "glxext.h" 45#include "indirect_dispatch.h" 46#include "indirect_table.h" 47#include "indirect_util.h" 48 49static char GLXServerVendorName[] = "SGI"; 50 51_X_HIDDEN int 52validGlxScreen(ClientPtr client, int screen, __GLXscreen ** pGlxScreen, 53 int *err) 54{ 55 /* 56 ** Check if screen exists. 57 */ 58 if (screen < 0 || screen >= screenInfo.numScreens) { 59 client->errorValue = screen; 60 *err = BadValue; 61 return FALSE; 62 } 63 *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); 64 65 return TRUE; 66} 67 68_X_HIDDEN int 69validGlxFBConfig(ClientPtr client, __GLXscreen * pGlxScreen, XID id, 70 __GLXconfig ** config, int *err) 71{ 72 __GLXconfig *m; 73 74 for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) 75 if (m->fbconfigID == id) { 76 *config = m; 77 return TRUE; 78 } 79 80 client->errorValue = id; 81 *err = __glXError(GLXBadFBConfig); 82 83 return FALSE; 84} 85 86static int 87validGlxVisual(ClientPtr client, __GLXscreen * pGlxScreen, XID id, 88 __GLXconfig ** config, int *err) 89{ 90 int i; 91 92 for (i = 0; i < pGlxScreen->numVisuals; i++) 93 if (pGlxScreen->visuals[i]->visualID == id) { 94 *config = pGlxScreen->visuals[i]; 95 return TRUE; 96 } 97 98 client->errorValue = id; 99 *err = BadValue; 100 101 return FALSE; 102} 103 104static int 105validGlxFBConfigForWindow(ClientPtr client, __GLXconfig * config, 106 DrawablePtr pDraw, int *err) 107{ 108 ScreenPtr pScreen = pDraw->pScreen; 109 VisualPtr pVisual = NULL; 110 XID vid; 111 int i; 112 113 vid = wVisual((WindowPtr) pDraw); 114 for (i = 0; i < pScreen->numVisuals; i++) { 115 if (pScreen->visuals[i].vid == vid) { 116 pVisual = &pScreen->visuals[i]; 117 break; 118 } 119 } 120 121 /* FIXME: What exactly should we check here... */ 122 if (pVisual->class != glxConvertToXVisualType(config->visualType) || 123 !(config->drawableType & GLX_WINDOW_BIT)) { 124 client->errorValue = pDraw->id; 125 *err = BadMatch; 126 return FALSE; 127 } 128 129 return TRUE; 130} 131 132_X_HIDDEN int 133validGlxContext(ClientPtr client, XID id, int access_mode, 134 __GLXcontext ** context, int *err) 135{ 136 *err = dixLookupResourceByType((void **) context, id, 137 __glXContextRes, client, access_mode); 138 if (*err != Success || (*context)->idExists == GL_FALSE) { 139 client->errorValue = id; 140 if (*err == BadValue || *err == Success) 141 *err = __glXError(GLXBadContext); 142 return FALSE; 143 } 144 145 return TRUE; 146} 147 148static int 149validGlxDrawable(ClientPtr client, XID id, int type, int access_mode, 150 __GLXdrawable ** drawable, int *err) 151{ 152 int rc; 153 154 rc = dixLookupResourceByType((void **) drawable, id, 155 __glXDrawableRes, client, access_mode); 156 if (rc != Success && rc != BadValue) { 157 *err = rc; 158 client->errorValue = id; 159 return FALSE; 160 } 161 162 /* If the ID of the glx drawable we looked up doesn't match the id 163 * we looked for, it's because we looked it up under the X 164 * drawable ID (see DoCreateGLXDrawable). */ 165 if (rc == BadValue || 166 (*drawable)->drawId != id || 167 (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) { 168 client->errorValue = id; 169 switch (type) { 170 case GLX_DRAWABLE_WINDOW: 171 *err = __glXError(GLXBadWindow); 172 return FALSE; 173 case GLX_DRAWABLE_PIXMAP: 174 *err = __glXError(GLXBadPixmap); 175 return FALSE; 176 case GLX_DRAWABLE_PBUFFER: 177 *err = __glXError(GLXBadPbuffer); 178 return FALSE; 179 case GLX_DRAWABLE_ANY: 180 *err = __glXError(GLXBadDrawable); 181 return FALSE; 182 } 183 } 184 185 return TRUE; 186} 187 188void 189__glXContextDestroy(__GLXcontext * context) 190{ 191 lastGLContext = NULL; 192} 193 194static void 195__glXdirectContextDestroy(__GLXcontext * context) 196{ 197 __glXContextDestroy(context); 198 free(context); 199} 200 201static int 202__glXdirectContextLoseCurrent(__GLXcontext * context) 203{ 204 return GL_TRUE; 205} 206 207_X_HIDDEN __GLXcontext * 208__glXdirectContextCreate(__GLXscreen * screen, 209 __GLXconfig * modes, __GLXcontext * shareContext) 210{ 211 __GLXcontext *context; 212 213 context = calloc(1, sizeof(__GLXcontext)); 214 if (context == NULL) 215 return NULL; 216 217 context->destroy = __glXdirectContextDestroy; 218 context->loseCurrent = __glXdirectContextLoseCurrent; 219 220 return context; 221} 222 223/** 224 * Create a GL context with the given properties. This routine is used 225 * to implement \c glXCreateContext, \c glXCreateNewContext, and 226 * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way 227 * that GLXFBConfigs are implemented. Basically, the FBConfigID is the 228 * same as the VisualID. 229 */ 230 231static int 232DoCreateContext(__GLXclientState * cl, GLXContextID gcId, 233 GLXContextID shareList, __GLXconfig * config, 234 __GLXscreen * pGlxScreen, GLboolean isDirect) 235{ 236 ClientPtr client = cl->client; 237 __GLXcontext *glxc, *shareglxc; 238 int err; 239 240 LEGAL_NEW_RESOURCE(gcId, client); 241 242 /* 243 ** Find the display list space that we want to share. 244 ** 245 ** NOTE: In a multithreaded X server, we would need to keep a reference 246 ** count for each display list so that if one client detroyed a list that 247 ** another client was using, the list would not really be freed until it 248 ** was no longer in use. Since this sample implementation has no support 249 ** for multithreaded servers, we don't do this. 250 */ 251 if (shareList == None) { 252 shareglxc = 0; 253 } 254 else { 255 if (!validGlxContext(client, shareList, DixReadAccess, 256 &shareglxc, &err)) 257 return err; 258 259 /* Page 26 (page 32 of the PDF) of the GLX 1.4 spec says: 260 * 261 * "The server context state for all sharing contexts must exist 262 * in a single address space or a BadMatch error is generated." 263 * 264 * If the share context is indirect, force the new context to also be 265 * indirect. If the shard context is direct but the new context 266 * cannot be direct, generate BadMatch. 267 */ 268 if (shareglxc->isDirect && !isDirect) { 269 client->errorValue = shareList; 270 return BadMatch; 271 } 272 else if (!shareglxc->isDirect) { 273 /* 274 ** Create an indirect context regardless of what the client asked 275 ** for; this way we can share display list space with shareList. 276 */ 277 isDirect = GL_FALSE; 278 } 279 } 280 281 /* 282 ** Allocate memory for the new context 283 */ 284 if (!isDirect) { 285 /* Only allow creating indirect GLX contexts if allowed by 286 * server command line. Indirect GLX is of limited use (since 287 * it's only GL 1.4), it's slower than direct contexts, and 288 * it's a massive attack surface for buffer overflow type 289 * errors. 290 */ 291 if (!enableIndirectGLX) { 292 client->errorValue = isDirect; 293 return BadValue; 294 } 295 296 /* Without any attributes, the only error that the driver should be 297 * able to generate is BadAlloc. As result, just drop the error 298 * returned from the driver on the floor. 299 */ 300 glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc, 301 0, NULL, &err); 302 } 303 else 304 glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc); 305 if (!glxc) { 306 return BadAlloc; 307 } 308 309 /* Initialize the GLXcontext structure. 310 */ 311 glxc->pGlxScreen = pGlxScreen; 312 glxc->config = config; 313 glxc->id = gcId; 314 glxc->share_id = shareList; 315 glxc->idExists = GL_TRUE; 316 glxc->currentClient = NULL; 317 glxc->isDirect = isDirect; 318 glxc->hasUnflushedCommands = GL_FALSE; 319 glxc->renderMode = GL_RENDER; 320 glxc->feedbackBuf = NULL; 321 glxc->feedbackBufSize = 0; 322 glxc->selectBuf = NULL; 323 glxc->selectBufSize = 0; 324 glxc->drawPriv = NULL; 325 glxc->readPriv = NULL; 326 327 /* The GLX_ARB_create_context_robustness spec says: 328 * 329 * "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 330 * is GLX_NO_RESET_NOTIFICATION_ARB." 331 * 332 * Without using glXCreateContextAttribsARB, there is no way to specify a 333 * non-default reset notification strategy. 334 */ 335 glxc->resetNotificationStrategy = GLX_NO_RESET_NOTIFICATION_ARB; 336 337#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 338 /* The GLX_ARB_context_flush_control spec says: 339 * 340 * "The default value [for GLX_CONTEXT_RELEASE_BEHAVIOR] is 341 * CONTEXT_RELEASE_BEHAVIOR_FLUSH, and may in some cases be changed 342 * using platform-specific context creation extensions." 343 * 344 * Without using glXCreateContextAttribsARB, there is no way to specify a 345 * non-default release behavior. 346 */ 347 glxc->releaseBehavior = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB; 348#endif 349 350 /* Add the new context to the various global tables of GLX contexts. 351 */ 352 if (!__glXAddContext(glxc)) { 353 (*glxc->destroy) (glxc); 354 client->errorValue = gcId; 355 return BadAlloc; 356 } 357 358 return Success; 359} 360 361int 362__glXDisp_CreateContext(__GLXclientState * cl, GLbyte * pc) 363{ 364 ClientPtr client = cl->client; 365 xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; 366 __GLXconfig *config; 367 __GLXscreen *pGlxScreen; 368 int err; 369 370 REQUEST_SIZE_MATCH(xGLXCreateContextReq); 371 372 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 373 return err; 374 if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) 375 return err; 376 377 return DoCreateContext(cl, req->context, req->shareList, 378 config, pGlxScreen, req->isDirect); 379} 380 381int 382__glXDisp_CreateNewContext(__GLXclientState * cl, GLbyte * pc) 383{ 384 ClientPtr client = cl->client; 385 xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; 386 __GLXconfig *config; 387 __GLXscreen *pGlxScreen; 388 int err; 389 390 REQUEST_SIZE_MATCH(xGLXCreateNewContextReq); 391 392 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 393 return err; 394 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 395 return err; 396 397 return DoCreateContext(cl, req->context, req->shareList, 398 config, pGlxScreen, req->isDirect); 399} 400 401int 402__glXDisp_CreateContextWithConfigSGIX(__GLXclientState * cl, GLbyte * pc) 403{ 404 ClientPtr client = cl->client; 405 xGLXCreateContextWithConfigSGIXReq *req = 406 (xGLXCreateContextWithConfigSGIXReq *) pc; 407 __GLXconfig *config; 408 __GLXscreen *pGlxScreen; 409 int err; 410 411 REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq); 412 413 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 414 return err; 415 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 416 return err; 417 418 return DoCreateContext(cl, req->context, req->shareList, 419 config, pGlxScreen, req->isDirect); 420} 421 422int 423__glXDisp_DestroyContext(__GLXclientState * cl, GLbyte * pc) 424{ 425 ClientPtr client = cl->client; 426 xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc; 427 __GLXcontext *glxc; 428 int err; 429 430 REQUEST_SIZE_MATCH(xGLXDestroyContextReq); 431 432 if (!validGlxContext(cl->client, req->context, DixDestroyAccess, 433 &glxc, &err)) 434 return err; 435 436 glxc->idExists = GL_FALSE; 437 if (!glxc->currentClient) 438 FreeResourceByType(req->context, __glXContextRes, FALSE); 439 440 return Success; 441} 442 443/* 444 * This will return "deleted" contexts, ie, where idExists is GL_FALSE. 445 * Contrast validGlxContext, which will not. We're cheating here and 446 * using the XID as the context tag, which is fine as long as we defer 447 * actually destroying the context until it's no longer referenced, and 448 * block clients from trying to MakeCurrent on contexts that are on the 449 * way to destruction. Notice that DoMakeCurrent calls validGlxContext 450 * for new contexts but __glXLookupContextByTag for previous contexts. 451 */ 452__GLXcontext * 453__glXLookupContextByTag(__GLXclientState * cl, GLXContextTag tag) 454{ 455 __GLXcontext *ret; 456 457 if (dixLookupResourceByType((void **) &ret, tag, __glXContextRes, 458 cl->client, DixUseAccess) == Success) 459 return ret; 460 461 return NULL; 462} 463 464/*****************************************************************************/ 465 466static void 467StopUsingContext(__GLXcontext * glxc) 468{ 469 if (glxc) { 470 glxc->currentClient = NULL; 471 if (!glxc->idExists) { 472 FreeResourceByType(glxc->id, __glXContextRes, FALSE); 473 } 474 } 475} 476 477static void 478StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc) 479{ 480 glxc->currentClient = cl->client; 481} 482 483/** 484 * This is a helper function to handle the legacy (pre GLX 1.3) cases 485 * where passing an X window to glXMakeCurrent is valid. Given a 486 * resource ID, look up the GLX drawable if available, otherwise, make 487 * sure it's an X window and create a GLX drawable one the fly. 488 */ 489static __GLXdrawable * 490__glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client, 491 int *error) 492{ 493 DrawablePtr pDraw; 494 __GLXdrawable *pGlxDraw; 495 int rc; 496 497 if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, 498 DixWriteAccess, &pGlxDraw, &rc)) { 499 if (glxc != NULL && pGlxDraw->config != glxc->config) { 500 client->errorValue = drawId; 501 *error = BadMatch; 502 return NULL; 503 } 504 505 return pGlxDraw; 506 } 507 508 /* No active context and an unknown drawable, bail. */ 509 if (glxc == NULL) { 510 client->errorValue = drawId; 511 *error = BadMatch; 512 return NULL; 513 } 514 515 /* The drawId wasn't a GLX drawable. Make sure it's a window and 516 * create a GLXWindow for it. Check that the drawable screen 517 * matches the context screen and that the context fbconfig is 518 * compatible with the window visual. */ 519 520 rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess); 521 if (rc != Success || pDraw->type != DRAWABLE_WINDOW) { 522 client->errorValue = drawId; 523 *error = __glXError(GLXBadDrawable); 524 return NULL; 525 } 526 527 if (pDraw->pScreen != glxc->pGlxScreen->pScreen) { 528 client->errorValue = pDraw->pScreen->myNum; 529 *error = BadMatch; 530 return NULL; 531 } 532 533 if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error)) 534 return NULL; 535 536 pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen, 537 pDraw, drawId, 538 GLX_DRAWABLE_WINDOW, 539 drawId, glxc->config); 540 if (!pGlxDraw) { 541 *error = BadAlloc; 542 return NULL; 543 } 544 545 /* since we are creating the drawablePrivate, drawId should be new */ 546 if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) { 547 *error = BadAlloc; 548 return NULL; 549 } 550 551 return pGlxDraw; 552} 553 554/*****************************************************************************/ 555/* 556** Make an OpenGL context and drawable current. 557*/ 558 559static int 560DoMakeCurrent(__GLXclientState * cl, 561 GLXDrawable drawId, GLXDrawable readId, 562 GLXContextID contextId, GLXContextTag tag) 563{ 564 ClientPtr client = cl->client; 565 xGLXMakeCurrentReply reply; 566 __GLXcontext *glxc, *prevglxc; 567 __GLXdrawable *drawPriv = NULL; 568 __GLXdrawable *readPriv = NULL; 569 int error; 570 GLuint mask; 571 572 /* 573 ** If one is None and the other isn't, it's a bad match. 574 */ 575 576 mask = (drawId == None) ? (1 << 0) : 0; 577 mask |= (readId == None) ? (1 << 1) : 0; 578 mask |= (contextId == None) ? (1 << 2) : 0; 579 580 if ((mask != 0x00) && (mask != 0x07)) { 581 return BadMatch; 582 } 583 584 /* 585 ** Lookup old context. If we have one, it must be in a usable state. 586 */ 587 if (tag != 0) { 588 prevglxc = __glXLookupContextByTag(cl, tag); 589 if (!prevglxc) { 590 /* 591 ** Tag for previous context is invalid. 592 */ 593 return __glXError(GLXBadContextTag); 594 } 595 if (prevglxc->renderMode != GL_RENDER) { 596 /* Oops. Not in render mode render. */ 597 client->errorValue = prevglxc->id; 598 return __glXError(GLXBadContextState); 599 } 600 } 601 else { 602 prevglxc = 0; 603 } 604 605 /* 606 ** Lookup new context. It must not be current for someone else. 607 */ 608 if (contextId != None) { 609 int status; 610 611 if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error)) 612 return error; 613 if ((glxc != prevglxc) && glxc->currentClient) { 614 /* Context is current to somebody else */ 615 return BadAccess; 616 } 617 618 assert(drawId != None); 619 assert(readId != None); 620 621 drawPriv = __glXGetDrawable(glxc, drawId, client, &status); 622 if (drawPriv == NULL) 623 return status; 624 625 readPriv = __glXGetDrawable(glxc, readId, client, &status); 626 if (readPriv == NULL) 627 return status; 628 629 } 630 else { 631 /* Switching to no context. Ignore new drawable. */ 632 glxc = 0; 633 drawPriv = 0; 634 readPriv = 0; 635 } 636 637 if (prevglxc) { 638 /* 639 ** Flush the previous context if needed. 640 */ 641 Bool need_flush = GL_TRUE; 642#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 643 if (prevglxc->releaseBehavior == GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB) 644 need_flush = GL_FALSE; 645#endif 646 if (prevglxc->hasUnflushedCommands && need_flush) { 647 if (__glXForceCurrent(cl, tag, (int *) &error)) { 648 glFlush(); 649 prevglxc->hasUnflushedCommands = GL_FALSE; 650 } 651 else { 652 return error; 653 } 654 } 655 656 /* 657 ** Make the previous context not current. 658 */ 659 if (!(*prevglxc->loseCurrent) (prevglxc)) { 660 return __glXError(GLXBadContext); 661 } 662 lastGLContext = NULL; 663 if (!prevglxc->isDirect) { 664 prevglxc->drawPriv = NULL; 665 prevglxc->readPriv = NULL; 666 } 667 } 668 669 if ((glxc != 0) && !glxc->isDirect) { 670 671 glxc->drawPriv = drawPriv; 672 glxc->readPriv = readPriv; 673 674 /* make the context current */ 675 lastGLContext = glxc; 676 if (!(*glxc->makeCurrent) (glxc)) { 677 lastGLContext = NULL; 678 glxc->drawPriv = NULL; 679 glxc->readPriv = NULL; 680 return __glXError(GLXBadContext); 681 } 682 683 glxc->currentClient = client; 684 } 685 686 StopUsingContext(prevglxc); 687 688 reply = (xGLXMakeCurrentReply) { 689 .type = X_Reply, 690 .sequenceNumber = client->sequence, 691 .length = 0, 692 .contextTag = 0 693 }; 694 695 if (glxc) { 696 StartUsingContext(cl, glxc); 697 reply.contextTag = glxc->id; 698 } 699 700 if (client->swapped) { 701 __glXSwapMakeCurrentReply(client, &reply); 702 } 703 else { 704 WriteToClient(client, sz_xGLXMakeCurrentReply, &reply); 705 } 706 return Success; 707} 708 709int 710__glXDisp_MakeCurrent(__GLXclientState * cl, GLbyte * pc) 711{ 712 ClientPtr client = cl->client; 713 xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; 714 715 REQUEST_SIZE_MATCH(xGLXMakeCurrentReq); 716 717 return DoMakeCurrent(cl, req->drawable, req->drawable, 718 req->context, req->oldContextTag); 719} 720 721int 722__glXDisp_MakeContextCurrent(__GLXclientState * cl, GLbyte * pc) 723{ 724 ClientPtr client = cl->client; 725 xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; 726 727 REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq); 728 729 return DoMakeCurrent(cl, req->drawable, req->readdrawable, 730 req->context, req->oldContextTag); 731} 732 733int 734__glXDisp_MakeCurrentReadSGI(__GLXclientState * cl, GLbyte * pc) 735{ 736 ClientPtr client = cl->client; 737 xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; 738 739 REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq); 740 741 return DoMakeCurrent(cl, req->drawable, req->readable, 742 req->context, req->oldContextTag); 743} 744 745int 746__glXDisp_IsDirect(__GLXclientState * cl, GLbyte * pc) 747{ 748 ClientPtr client = cl->client; 749 xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc; 750 xGLXIsDirectReply reply; 751 __GLXcontext *glxc; 752 int err; 753 754 REQUEST_SIZE_MATCH(xGLXIsDirectReq); 755 756 if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err)) 757 return err; 758 759 reply = (xGLXIsDirectReply) { 760 .type = X_Reply, 761 .sequenceNumber = client->sequence, 762 .length = 0, 763 .isDirect = glxc->isDirect 764 }; 765 766 if (client->swapped) { 767 __glXSwapIsDirectReply(client, &reply); 768 } 769 else { 770 WriteToClient(client, sz_xGLXIsDirectReply, &reply); 771 } 772 773 return Success; 774} 775 776int 777__glXDisp_QueryVersion(__GLXclientState * cl, GLbyte * pc) 778{ 779 ClientPtr client = cl->client; 780 xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc; 781 xGLXQueryVersionReply reply; 782 GLuint major, minor; 783 784 REQUEST_SIZE_MATCH(xGLXQueryVersionReq); 785 786 major = req->majorVersion; 787 minor = req->minorVersion; 788 (void) major; 789 (void) minor; 790 791 /* 792 ** Server should take into consideration the version numbers sent by the 793 ** client if it wants to work with older clients; however, in this 794 ** implementation the server just returns its version number. 795 */ 796 reply = (xGLXQueryVersionReply) { 797 .type = X_Reply, 798 .sequenceNumber = client->sequence, 799 .length = 0, 800 .majorVersion = glxMajorVersion, 801 .minorVersion = glxMinorVersion 802 }; 803 804 if (client->swapped) { 805 __glXSwapQueryVersionReply(client, &reply); 806 } 807 else { 808 WriteToClient(client, sz_xGLXQueryVersionReply, &reply); 809 } 810 return Success; 811} 812 813int 814__glXDisp_WaitGL(__GLXclientState * cl, GLbyte * pc) 815{ 816 ClientPtr client = cl->client; 817 xGLXWaitGLReq *req = (xGLXWaitGLReq *) pc; 818 GLXContextTag tag; 819 __GLXcontext *glxc = NULL; 820 int error; 821 822 REQUEST_SIZE_MATCH(xGLXWaitGLReq); 823 824 tag = req->contextTag; 825 if (tag) { 826 glxc = __glXLookupContextByTag(cl, tag); 827 if (!glxc) 828 return __glXError(GLXBadContextTag); 829 830 if (!__glXForceCurrent(cl, req->contextTag, &error)) 831 return error; 832 833 glFinish(); 834 } 835 836 if (glxc && glxc->drawPriv->waitGL) 837 (*glxc->drawPriv->waitGL) (glxc->drawPriv); 838 839 return Success; 840} 841 842int 843__glXDisp_WaitX(__GLXclientState * cl, GLbyte * pc) 844{ 845 ClientPtr client = cl->client; 846 xGLXWaitXReq *req = (xGLXWaitXReq *) pc; 847 GLXContextTag tag; 848 __GLXcontext *glxc = NULL; 849 int error; 850 851 REQUEST_SIZE_MATCH(xGLXWaitXReq); 852 853 tag = req->contextTag; 854 if (tag) { 855 glxc = __glXLookupContextByTag(cl, tag); 856 if (!glxc) 857 return __glXError(GLXBadContextTag); 858 859 if (!__glXForceCurrent(cl, req->contextTag, &error)) 860 return error; 861 } 862 863 if (glxc && glxc->drawPriv->waitX) 864 (*glxc->drawPriv->waitX) (glxc->drawPriv); 865 866 return Success; 867} 868 869int 870__glXDisp_CopyContext(__GLXclientState * cl, GLbyte * pc) 871{ 872 ClientPtr client = cl->client; 873 xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc; 874 GLXContextID source; 875 GLXContextID dest; 876 GLXContextTag tag; 877 unsigned long mask; 878 __GLXcontext *src, *dst; 879 int error; 880 881 REQUEST_SIZE_MATCH(xGLXCopyContextReq); 882 883 source = req->source; 884 dest = req->dest; 885 tag = req->contextTag; 886 mask = req->mask; 887 if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error)) 888 return error; 889 if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error)) 890 return error; 891 892 /* 893 ** They must be in the same address space, and same screen. 894 ** NOTE: no support for direct rendering contexts here. 895 */ 896 if (src->isDirect || dst->isDirect || (src->pGlxScreen != dst->pGlxScreen)) { 897 client->errorValue = source; 898 return BadMatch; 899 } 900 901 /* 902 ** The destination context must not be current for any client. 903 */ 904 if (dst->currentClient) { 905 client->errorValue = dest; 906 return BadAccess; 907 } 908 909 if (tag) { 910 __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag); 911 912 if (!tagcx) { 913 return __glXError(GLXBadContextTag); 914 } 915 if (tagcx != src) { 916 /* 917 ** This would be caused by a faulty implementation of the client 918 ** library. 919 */ 920 return BadMatch; 921 } 922 /* 923 ** In this case, glXCopyContext is in both GL and X streams, in terms 924 ** of sequentiality. 925 */ 926 if (__glXForceCurrent(cl, tag, &error)) { 927 /* 928 ** Do whatever is needed to make sure that all preceding requests 929 ** in both streams are completed before the copy is executed. 930 */ 931 glFinish(); 932 tagcx->hasUnflushedCommands = GL_FALSE; 933 } 934 else { 935 return error; 936 } 937 } 938 /* 939 ** Issue copy. The only reason for failure is a bad mask. 940 */ 941 if (!(*dst->copy) (dst, src, mask)) { 942 client->errorValue = mask; 943 return BadValue; 944 } 945 return Success; 946} 947 948enum { 949 GLX_VIS_CONFIG_UNPAIRED = 18, 950 GLX_VIS_CONFIG_PAIRED = 22 951}; 952 953enum { 954 GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED 955}; 956 957int 958__glXDisp_GetVisualConfigs(__GLXclientState * cl, GLbyte * pc) 959{ 960 xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; 961 ClientPtr client = cl->client; 962 xGLXGetVisualConfigsReply reply; 963 __GLXscreen *pGlxScreen; 964 __GLXconfig *modes; 965 CARD32 buf[GLX_VIS_CONFIG_TOTAL]; 966 int p, i, err; 967 968 __GLX_DECLARE_SWAP_VARIABLES; 969 __GLX_DECLARE_SWAP_ARRAY_VARIABLES; 970 971 REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq); 972 973 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 974 return err; 975 976 reply = (xGLXGetVisualConfigsReply) { 977 .type = X_Reply, 978 .sequenceNumber = client->sequence, 979 .length = (pGlxScreen->numVisuals * 980 __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2, 981 .numVisuals = pGlxScreen->numVisuals, 982 .numProps = GLX_VIS_CONFIG_TOTAL 983 }; 984 985 if (client->swapped) { 986 __GLX_SWAP_SHORT(&reply.sequenceNumber); 987 __GLX_SWAP_INT(&reply.length); 988 __GLX_SWAP_INT(&reply.numVisuals); 989 __GLX_SWAP_INT(&reply.numProps); 990 } 991 992 WriteToClient(client, sz_xGLXGetVisualConfigsReply, &reply); 993 994 for (i = 0; i < pGlxScreen->numVisuals; i++) { 995 modes = pGlxScreen->visuals[i]; 996 997 p = 0; 998 buf[p++] = modes->visualID; 999 buf[p++] = glxConvertToXVisualType(modes->visualType); 1000 buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE; 1001 1002 buf[p++] = modes->redBits; 1003 buf[p++] = modes->greenBits; 1004 buf[p++] = modes->blueBits; 1005 buf[p++] = modes->alphaBits; 1006 buf[p++] = modes->accumRedBits; 1007 buf[p++] = modes->accumGreenBits; 1008 buf[p++] = modes->accumBlueBits; 1009 buf[p++] = modes->accumAlphaBits; 1010 1011 buf[p++] = modes->doubleBufferMode; 1012 buf[p++] = modes->stereoMode; 1013 1014 buf[p++] = modes->rgbBits; 1015 buf[p++] = modes->depthBits; 1016 buf[p++] = modes->stencilBits; 1017 buf[p++] = modes->numAuxBuffers; 1018 buf[p++] = modes->level; 1019 1020 assert(p == GLX_VIS_CONFIG_UNPAIRED); 1021 /* 1022 ** Add token/value pairs for extensions. 1023 */ 1024 buf[p++] = GLX_VISUAL_CAVEAT_EXT; 1025 buf[p++] = modes->visualRating; 1026 buf[p++] = GLX_TRANSPARENT_TYPE; 1027 buf[p++] = modes->transparentPixel; 1028 buf[p++] = GLX_TRANSPARENT_RED_VALUE; 1029 buf[p++] = modes->transparentRed; 1030 buf[p++] = GLX_TRANSPARENT_GREEN_VALUE; 1031 buf[p++] = modes->transparentGreen; 1032 buf[p++] = GLX_TRANSPARENT_BLUE_VALUE; 1033 buf[p++] = modes->transparentBlue; 1034 buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE; 1035 buf[p++] = modes->transparentAlpha; 1036 buf[p++] = GLX_TRANSPARENT_INDEX_VALUE; 1037 buf[p++] = modes->transparentIndex; 1038 buf[p++] = GLX_SAMPLES_SGIS; 1039 buf[p++] = modes->samples; 1040 buf[p++] = GLX_SAMPLE_BUFFERS_SGIS; 1041 buf[p++] = modes->sampleBuffers; 1042 /* Add attribute only if its value is not default. */ 1043 if (modes->sRGBCapable != GL_FALSE) { 1044 buf[p++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT; 1045 buf[p++] = modes->sRGBCapable; 1046 } 1047 /* Don't add visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)? 1048 * Pad the remaining place with zeroes, so that attributes count is constant. */ 1049 while (p < GLX_VIS_CONFIG_TOTAL) { 1050 buf[p++] = 0; 1051 buf[p++] = 0; 1052 } 1053 1054 assert(p == GLX_VIS_CONFIG_TOTAL); 1055 if (client->swapped) { 1056 __GLX_SWAP_INT_ARRAY(buf, p); 1057 } 1058 WriteToClient(client, __GLX_SIZE_CARD32 * p, buf); 1059 } 1060 return Success; 1061} 1062 1063#define __GLX_TOTAL_FBCONFIG_ATTRIBS (44) 1064#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2) 1065/** 1066 * Send the set of GLXFBConfigs to the client. There is not currently 1067 * and interface into the driver on the server-side to get GLXFBConfigs, 1068 * so we "invent" some based on the \c __GLXvisualConfig structures that 1069 * the driver does supply. 1070 * 1071 * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX 1072 * is the same, so this routine pulls double duty. 1073 */ 1074 1075static int 1076DoGetFBConfigs(__GLXclientState * cl, unsigned screen) 1077{ 1078 ClientPtr client = cl->client; 1079 xGLXGetFBConfigsReply reply; 1080 __GLXscreen *pGlxScreen; 1081 CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH]; 1082 int p, err; 1083 __GLXconfig *modes; 1084 1085 __GLX_DECLARE_SWAP_VARIABLES; 1086 __GLX_DECLARE_SWAP_ARRAY_VARIABLES; 1087 1088 if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err)) 1089 return err; 1090 1091 reply = (xGLXGetFBConfigsReply) { 1092 .type = X_Reply, 1093 .sequenceNumber = client->sequence, 1094 .length = __GLX_FBCONFIG_ATTRIBS_LENGTH * pGlxScreen->numFBConfigs, 1095 .numFBConfigs = pGlxScreen->numFBConfigs, 1096 .numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS 1097 }; 1098 1099 if (client->swapped) { 1100 __GLX_SWAP_SHORT(&reply.sequenceNumber); 1101 __GLX_SWAP_INT(&reply.length); 1102 __GLX_SWAP_INT(&reply.numFBConfigs); 1103 __GLX_SWAP_INT(&reply.numAttribs); 1104 } 1105 1106 WriteToClient(client, sz_xGLXGetFBConfigsReply, &reply); 1107 1108 for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) { 1109 p = 0; 1110 1111#define WRITE_PAIR(tag,value) \ 1112 do { buf[p++] = tag ; buf[p++] = value ; } while( 0 ) 1113 1114 WRITE_PAIR(GLX_VISUAL_ID, modes->visualID); 1115 WRITE_PAIR(GLX_FBCONFIG_ID, modes->fbconfigID); 1116 WRITE_PAIR(GLX_X_RENDERABLE, GL_TRUE); 1117 1118 WRITE_PAIR(GLX_RGBA, 1119 (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE); 1120 WRITE_PAIR(GLX_RENDER_TYPE, modes->renderType); 1121 WRITE_PAIR(GLX_DOUBLEBUFFER, modes->doubleBufferMode); 1122 WRITE_PAIR(GLX_STEREO, modes->stereoMode); 1123 1124 WRITE_PAIR(GLX_BUFFER_SIZE, modes->rgbBits); 1125 WRITE_PAIR(GLX_LEVEL, modes->level); 1126 WRITE_PAIR(GLX_AUX_BUFFERS, modes->numAuxBuffers); 1127 WRITE_PAIR(GLX_RED_SIZE, modes->redBits); 1128 WRITE_PAIR(GLX_GREEN_SIZE, modes->greenBits); 1129 WRITE_PAIR(GLX_BLUE_SIZE, modes->blueBits); 1130 WRITE_PAIR(GLX_ALPHA_SIZE, modes->alphaBits); 1131 WRITE_PAIR(GLX_ACCUM_RED_SIZE, modes->accumRedBits); 1132 WRITE_PAIR(GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits); 1133 WRITE_PAIR(GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits); 1134 WRITE_PAIR(GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits); 1135 WRITE_PAIR(GLX_DEPTH_SIZE, modes->depthBits); 1136 WRITE_PAIR(GLX_STENCIL_SIZE, modes->stencilBits); 1137 WRITE_PAIR(GLX_X_VISUAL_TYPE, modes->visualType); 1138 WRITE_PAIR(GLX_CONFIG_CAVEAT, modes->visualRating); 1139 WRITE_PAIR(GLX_TRANSPARENT_TYPE, modes->transparentPixel); 1140 WRITE_PAIR(GLX_TRANSPARENT_RED_VALUE, modes->transparentRed); 1141 WRITE_PAIR(GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen); 1142 WRITE_PAIR(GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue); 1143 WRITE_PAIR(GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha); 1144 WRITE_PAIR(GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex); 1145 WRITE_PAIR(GLX_SWAP_METHOD_OML, modes->swapMethod); 1146 WRITE_PAIR(GLX_SAMPLES_SGIS, modes->samples); 1147 WRITE_PAIR(GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers); 1148 WRITE_PAIR(GLX_VISUAL_SELECT_GROUP_SGIX, modes->visualSelectGroup); 1149 WRITE_PAIR(GLX_DRAWABLE_TYPE, modes->drawableType); 1150 WRITE_PAIR(GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb); 1151 WRITE_PAIR(GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba); 1152 WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture); 1153 WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1154 modes->bindToTextureTargets); 1155 /* can't report honestly until mesa is fixed */ 1156 WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE); 1157 if (modes->drawableType & GLX_PBUFFER_BIT) { 1158 WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth); 1159 WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight); 1160 WRITE_PAIR(GLX_MAX_PBUFFER_PIXELS, modes->maxPbufferPixels); 1161 WRITE_PAIR(GLX_OPTIMAL_PBUFFER_WIDTH_SGIX, 1162 modes->optimalPbufferWidth); 1163 WRITE_PAIR(GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX, 1164 modes->optimalPbufferHeight); 1165 } 1166 /* Add attribute only if its value is not default. */ 1167 if (modes->sRGBCapable != GL_FALSE) { 1168 WRITE_PAIR(GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, modes->sRGBCapable); 1169 } 1170 /* Pad the remaining place with zeroes, so that attributes count is constant. */ 1171 while (p < __GLX_FBCONFIG_ATTRIBS_LENGTH) { 1172 WRITE_PAIR(0, 0); 1173 } 1174 assert(p == __GLX_FBCONFIG_ATTRIBS_LENGTH); 1175 1176 if (client->swapped) { 1177 __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH); 1178 } 1179 WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH, 1180 (char *) buf); 1181 } 1182 return Success; 1183} 1184 1185int 1186__glXDisp_GetFBConfigs(__GLXclientState * cl, GLbyte * pc) 1187{ 1188 ClientPtr client = cl->client; 1189 xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; 1190 1191 REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq); 1192 return DoGetFBConfigs(cl, req->screen); 1193} 1194 1195int 1196__glXDisp_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc) 1197{ 1198 ClientPtr client = cl->client; 1199 xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc; 1200 1201 /* work around mesa bug, don't use REQUEST_SIZE_MATCH */ 1202 REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq); 1203 return DoGetFBConfigs(cl, req->screen); 1204} 1205 1206GLboolean 1207__glXDrawableInit(__GLXdrawable * drawable, 1208 __GLXscreen * screen, DrawablePtr pDraw, int type, 1209 XID drawId, __GLXconfig * config) 1210{ 1211 drawable->pDraw = pDraw; 1212 drawable->type = type; 1213 drawable->drawId = drawId; 1214 drawable->otherId = 0; 1215 drawable->config = config; 1216 drawable->eventMask = 0; 1217 1218 return GL_TRUE; 1219} 1220 1221void 1222__glXDrawableRelease(__GLXdrawable * drawable) 1223{ 1224} 1225 1226static int 1227DoCreateGLXDrawable(ClientPtr client, __GLXscreen * pGlxScreen, 1228 __GLXconfig * config, DrawablePtr pDraw, XID drawableId, 1229 XID glxDrawableId, int type) 1230{ 1231 __GLXdrawable *pGlxDraw; 1232 1233 if (pGlxScreen->pScreen != pDraw->pScreen) 1234 return BadMatch; 1235 1236 pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw, 1237 drawableId, type, 1238 glxDrawableId, config); 1239 if (pGlxDraw == NULL) 1240 return BadAlloc; 1241 1242 if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) 1243 return BadAlloc; 1244 1245 /* 1246 * Windows aren't refcounted, so track both the X and the GLX window 1247 * so we get called regardless of destruction order. 1248 */ 1249 // XXXMRG xorg-server 1.10 1250 if (drawableId != glxDrawableId && (type == GLX_DRAWABLE_WINDOW /*|| type == GLX_DRAWABLE_PIXMAP*/) && 1251 !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) 1252 /*pGlxDraw->destroy (pGlxDraw);*/ 1253 return BadAlloc; 1254 1255 return Success; 1256} 1257 1258static int 1259DoCreateGLXPixmap(ClientPtr client, __GLXscreen * pGlxScreen, 1260 __GLXconfig * config, XID drawableId, XID glxDrawableId) 1261{ 1262 DrawablePtr pDraw; 1263 int err; 1264 1265 LEGAL_NEW_RESOURCE(glxDrawableId, client); 1266 1267 err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess); 1268 if (err != Success) { 1269 client->errorValue = drawableId; 1270 return err; 1271 } 1272 if (pDraw->type != DRAWABLE_PIXMAP) { 1273 client->errorValue = drawableId; 1274 return BadPixmap; 1275 } 1276 1277 err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, 1278 glxDrawableId, GLX_DRAWABLE_PIXMAP); 1279 1280 if (err == Success) 1281 ((PixmapPtr) pDraw)->refcnt++; 1282 1283 return err; 1284} 1285 1286static void 1287determineTextureTarget(ClientPtr client, XID glxDrawableID, 1288 CARD32 *attribs, CARD32 numAttribs) 1289{ 1290 GLenum target = 0; 1291 GLenum format = 0; 1292 int i, err; 1293 __GLXdrawable *pGlxDraw; 1294 1295 if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP, 1296 DixWriteAccess, &pGlxDraw, &err)) 1297 /* We just added it in CreatePixmap, so we should never get here. */ 1298 return; 1299 1300 for (i = 0; i < numAttribs; i++) { 1301 if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { 1302 switch (attribs[2 * i + 1]) { 1303 case GLX_TEXTURE_2D_EXT: 1304 target = GL_TEXTURE_2D; 1305 break; 1306 case GLX_TEXTURE_RECTANGLE_EXT: 1307 target = GL_TEXTURE_RECTANGLE_ARB; 1308 break; 1309 } 1310 } 1311 1312 if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT) 1313 format = attribs[2 * i + 1]; 1314 } 1315 1316 if (!target) { 1317 int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height; 1318 1319 if (h & (h - 1) || w & (w - 1)) 1320 target = GL_TEXTURE_RECTANGLE_ARB; 1321 else 1322 target = GL_TEXTURE_2D; 1323 } 1324 1325 pGlxDraw->target = target; 1326 pGlxDraw->format = format; 1327} 1328 1329int 1330__glXDisp_CreateGLXPixmap(__GLXclientState * cl, GLbyte * pc) 1331{ 1332 ClientPtr client = cl->client; 1333 xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; 1334 __GLXconfig *config; 1335 __GLXscreen *pGlxScreen; 1336 int err; 1337 1338 REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq); 1339 1340 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1341 return err; 1342 if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) 1343 return err; 1344 1345 return DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1346 req->pixmap, req->glxpixmap); 1347} 1348 1349int 1350__glXDisp_CreatePixmap(__GLXclientState * cl, GLbyte * pc) 1351{ 1352 ClientPtr client = cl->client; 1353 xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; 1354 __GLXconfig *config; 1355 __GLXscreen *pGlxScreen; 1356 int err; 1357 1358 REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq); 1359 if (req->numAttribs > (UINT32_MAX >> 3)) { 1360 client->errorValue = req->numAttribs; 1361 return BadValue; 1362 } 1363 REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3); 1364 1365 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1366 return err; 1367 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1368 return err; 1369 1370 err = DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1371 req->pixmap, req->glxpixmap); 1372 if (err != Success) 1373 return err; 1374 1375 determineTextureTarget(cl->client, req->glxpixmap, 1376 (CARD32 *) (req + 1), req->numAttribs); 1377 1378 return Success; 1379} 1380 1381int 1382__glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState * cl, GLbyte * pc) 1383{ 1384 ClientPtr client = cl->client; 1385 xGLXCreateGLXPixmapWithConfigSGIXReq *req = 1386 (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; 1387 __GLXconfig *config; 1388 __GLXscreen *pGlxScreen; 1389 int err; 1390 1391 REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq); 1392 1393 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1394 return err; 1395 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1396 return err; 1397 1398 return DoCreateGLXPixmap(cl->client, pGlxScreen, 1399 config, req->pixmap, req->glxpixmap); 1400} 1401 1402static int 1403DoDestroyDrawable(__GLXclientState * cl, XID glxdrawable, int type) 1404{ 1405 __GLXdrawable *pGlxDraw; 1406 int err; 1407 1408 if (!validGlxDrawable(cl->client, glxdrawable, type, 1409 DixDestroyAccess, &pGlxDraw, &err)) 1410 return err; 1411 1412 FreeResource(glxdrawable, FALSE); 1413 1414 return Success; 1415} 1416 1417int 1418__glXDisp_DestroyGLXPixmap(__GLXclientState * cl, GLbyte * pc) 1419{ 1420 ClientPtr client = cl->client; 1421 xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; 1422 1423 REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq); 1424 1425 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1426} 1427 1428int 1429__glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc) 1430{ 1431 ClientPtr client = cl->client; 1432 xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; 1433 1434 /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set 1435 * length to 3 instead of 2 */ 1436 REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq); 1437 1438 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1439} 1440 1441static int 1442DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, 1443 int width, int height, XID glxDrawableId) 1444{ 1445 __GLXconfig *config; 1446 __GLXscreen *pGlxScreen; 1447 PixmapPtr pPixmap; 1448 int err; 1449 1450 LEGAL_NEW_RESOURCE(glxDrawableId, client); 1451 1452 if (!validGlxScreen(client, screenNum, &pGlxScreen, &err)) 1453 return err; 1454 if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err)) 1455 return err; 1456 1457 __glXenterServer(GL_FALSE); 1458 pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen, 1459 width, height, 1460 config->rgbBits, 0); 1461 __glXleaveServer(GL_FALSE); 1462 if (!pPixmap) 1463 return BadAlloc; 1464 1465 /* Assign the pixmap the same id as the pbuffer and add it as a 1466 * resource so it and the DRI2 drawable will be reclaimed when the 1467 * pbuffer is destroyed. */ 1468 pPixmap->drawable.id = glxDrawableId; 1469 if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap)) 1470 return BadAlloc; 1471 1472 return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, 1473 glxDrawableId, glxDrawableId, 1474 GLX_DRAWABLE_PBUFFER); 1475} 1476 1477int 1478__glXDisp_CreatePbuffer(__GLXclientState * cl, GLbyte * pc) 1479{ 1480 ClientPtr client = cl->client; 1481 xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; 1482 CARD32 *attrs; 1483 int width, height, i; 1484 1485 REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq); 1486 if (req->numAttribs > (UINT32_MAX >> 3)) { 1487 client->errorValue = req->numAttribs; 1488 return BadValue; 1489 } 1490 REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3); 1491 1492 attrs = (CARD32 *) (req + 1); 1493 width = 0; 1494 height = 0; 1495 1496 for (i = 0; i < req->numAttribs; i++) { 1497 switch (attrs[i * 2]) { 1498 case GLX_PBUFFER_WIDTH: 1499 width = attrs[i * 2 + 1]; 1500 break; 1501 case GLX_PBUFFER_HEIGHT: 1502 height = attrs[i * 2 + 1]; 1503 break; 1504 case GLX_LARGEST_PBUFFER: 1505 /* FIXME: huh... */ 1506 break; 1507 } 1508 } 1509 1510 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1511 width, height, req->pbuffer); 1512} 1513 1514int 1515__glXDisp_CreateGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc) 1516{ 1517 ClientPtr client = cl->client; 1518 xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; 1519 1520 REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq); 1521 1522 /* 1523 * We should really handle attributes correctly, but this extension 1524 * is so rare I have difficulty caring. 1525 */ 1526 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1527 req->width, req->height, req->pbuffer); 1528} 1529 1530int 1531__glXDisp_DestroyPbuffer(__GLXclientState * cl, GLbyte * pc) 1532{ 1533 ClientPtr client = cl->client; 1534 xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; 1535 1536 REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq); 1537 1538 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1539} 1540 1541int 1542__glXDisp_DestroyGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc) 1543{ 1544 ClientPtr client = cl->client; 1545 xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc; 1546 1547 REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq); 1548 1549 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1550} 1551 1552static int 1553DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable, 1554 int numAttribs, CARD32 *attribs) 1555{ 1556 __GLXdrawable *pGlxDraw; 1557 int i, err; 1558 1559 if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY, 1560 DixSetAttrAccess, &pGlxDraw, &err)) 1561 return err; 1562 1563 for (i = 0; i < numAttribs; i++) { 1564 switch (attribs[i * 2]) { 1565 case GLX_EVENT_MASK: 1566 /* All we do is to record the event mask so we can send it 1567 * back when queried. We never actually clobber the 1568 * pbuffers, so we never need to send out the event. */ 1569 pGlxDraw->eventMask = attribs[i * 2 + 1]; 1570 break; 1571 } 1572 } 1573 1574 return Success; 1575} 1576 1577int 1578__glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc) 1579{ 1580 ClientPtr client = cl->client; 1581 xGLXChangeDrawableAttributesReq *req = 1582 (xGLXChangeDrawableAttributesReq *) pc; 1583 1584 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq); 1585 if (req->numAttribs > (UINT32_MAX >> 3)) { 1586 client->errorValue = req->numAttribs; 1587 return BadValue; 1588 } 1589#if 0 1590 /* mesa sends an additional 8 bytes */ 1591 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); 1592#else 1593 if (((sizeof(xGLXChangeDrawableAttributesReq) + 1594 (req->numAttribs << 3)) >> 2) < client->req_len) 1595 return BadLength; 1596#endif 1597 1598 return DoChangeDrawableAttributes(cl->client, req->drawable, 1599 req->numAttribs, (CARD32 *) (req + 1)); 1600} 1601 1602int 1603__glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc) 1604{ 1605 ClientPtr client = cl->client; 1606 xGLXChangeDrawableAttributesSGIXReq *req = 1607 (xGLXChangeDrawableAttributesSGIXReq *) pc; 1608 1609 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq); 1610 if (req->numAttribs > (UINT32_MAX >> 3)) { 1611 client->errorValue = req->numAttribs; 1612 return BadValue; 1613 } 1614 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, 1615 req->numAttribs << 3); 1616 1617 return DoChangeDrawableAttributes(cl->client, req->drawable, 1618 req->numAttribs, (CARD32 *) (req + 1)); 1619} 1620 1621int 1622__glXDisp_CreateWindow(__GLXclientState * cl, GLbyte * pc) 1623{ 1624 xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; 1625 __GLXconfig *config; 1626 __GLXscreen *pGlxScreen; 1627 ClientPtr client = cl->client; 1628 DrawablePtr pDraw; 1629 int err; 1630 1631 REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq); 1632 if (req->numAttribs > (UINT32_MAX >> 3)) { 1633 client->errorValue = req->numAttribs; 1634 return BadValue; 1635 } 1636 REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3); 1637 1638 LEGAL_NEW_RESOURCE(req->glxwindow, client); 1639 1640 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 1641 return err; 1642 if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err)) 1643 return err; 1644 1645 err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess); 1646 if (err != Success || pDraw->type != DRAWABLE_WINDOW) { 1647 client->errorValue = req->window; 1648 return BadWindow; 1649 } 1650 1651 if (!validGlxFBConfigForWindow(client, config, pDraw, &err)) 1652 return err; 1653 1654 return DoCreateGLXDrawable(client, pGlxScreen, config, 1655 pDraw, req->window, 1656 req->glxwindow, GLX_DRAWABLE_WINDOW); 1657} 1658 1659int 1660__glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc) 1661{ 1662 ClientPtr client = cl->client; 1663 xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; 1664 1665 /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */ 1666 REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq); 1667 1668 return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); 1669} 1670 1671/*****************************************************************************/ 1672 1673/* 1674** NOTE: There is no portable implementation for swap buffers as of 1675** this time that is of value. Consequently, this code must be 1676** implemented by somebody other than SGI. 1677*/ 1678int 1679__glXDisp_SwapBuffers(__GLXclientState * cl, GLbyte * pc) 1680{ 1681 ClientPtr client = cl->client; 1682 xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; 1683 GLXContextTag tag; 1684 XID drawId; 1685 __GLXcontext *glxc = NULL; 1686 __GLXdrawable *pGlxDraw; 1687 int error; 1688 1689 REQUEST_SIZE_MATCH(xGLXSwapBuffersReq); 1690 1691 tag = req->contextTag; 1692 drawId = req->drawable; 1693 if (tag) { 1694 glxc = __glXLookupContextByTag(cl, tag); 1695 if (!glxc) { 1696 return __glXError(GLXBadContextTag); 1697 } 1698 /* 1699 ** The calling thread is swapping its current drawable. In this case, 1700 ** glxSwapBuffers is in both GL and X streams, in terms of 1701 ** sequentiality. 1702 */ 1703 if (__glXForceCurrent(cl, tag, &error)) { 1704 /* 1705 ** Do whatever is needed to make sure that all preceding requests 1706 ** in both streams are completed before the swap is executed. 1707 */ 1708 glFinish(); 1709 glxc->hasUnflushedCommands = GL_FALSE; 1710 } 1711 else { 1712 return error; 1713 } 1714 } 1715 1716 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1717 if (pGlxDraw == NULL) 1718 return error; 1719 1720 if (pGlxDraw->type == DRAWABLE_WINDOW && 1721 (*pGlxDraw->swapBuffers) (cl->client, pGlxDraw) == GL_FALSE) 1722 return __glXError(GLXBadDrawable); 1723 1724 return Success; 1725} 1726 1727static int 1728DoQueryContext(__GLXclientState * cl, GLXContextID gcId) 1729{ 1730 ClientPtr client = cl->client; 1731 __GLXcontext *ctx; 1732 xGLXQueryContextInfoEXTReply reply; 1733 int nProps = 3; 1734 int sendBuf[nProps * 2]; 1735 int nReplyBytes; 1736 int err; 1737 1738 if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err)) 1739 return err; 1740 1741 reply = (xGLXQueryContextInfoEXTReply) { 1742 .type = X_Reply, 1743 .sequenceNumber = client->sequence, 1744 .length = nProps << 1, 1745 .n = nProps 1746 }; 1747 1748 nReplyBytes = reply.length << 2; 1749 sendBuf[0] = GLX_SHARE_CONTEXT_EXT; 1750 sendBuf[1] = (int) (ctx->share_id); 1751 sendBuf[2] = GLX_VISUAL_ID_EXT; 1752 sendBuf[3] = (int) (ctx->config->visualID); 1753 sendBuf[4] = GLX_SCREEN_EXT; 1754 sendBuf[5] = (int) (ctx->pGlxScreen->pScreen->myNum); 1755 1756 if (client->swapped) { 1757 __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf); 1758 } 1759 else { 1760 WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, &reply); 1761 WriteToClient(client, nReplyBytes, sendBuf); 1762 } 1763 1764 return Success; 1765} 1766 1767int 1768__glXDisp_QueryContextInfoEXT(__GLXclientState * cl, GLbyte * pc) 1769{ 1770 ClientPtr client = cl->client; 1771 xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc; 1772 1773 REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq); 1774 1775 return DoQueryContext(cl, req->context); 1776} 1777 1778int 1779__glXDisp_QueryContext(__GLXclientState * cl, GLbyte * pc) 1780{ 1781 ClientPtr client = cl->client; 1782 xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc; 1783 1784 REQUEST_SIZE_MATCH(xGLXQueryContextReq); 1785 1786 return DoQueryContext(cl, req->context); 1787} 1788 1789int 1790__glXDisp_BindTexImageEXT(__GLXclientState * cl, GLbyte * pc) 1791{ 1792 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1793 ClientPtr client = cl->client; 1794 __GLXcontext *context; 1795 __GLXdrawable *pGlxDraw; 1796 GLXDrawable drawId; 1797 int buffer; 1798 int error; 1799 CARD32 num_attribs; 1800 1801 if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len) 1802 return BadLength; 1803 1804 pc += __GLX_VENDPRIV_HDR_SIZE; 1805 1806 drawId = *((CARD32 *) (pc)); 1807 buffer = *((INT32 *) (pc + 4)); 1808 num_attribs = *((CARD32 *) (pc + 8)); 1809 if (num_attribs > (UINT32_MAX >> 3)) { 1810 client->errorValue = num_attribs; 1811 return BadValue; 1812 } 1813 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3)); 1814 1815 if (buffer != GLX_FRONT_LEFT_EXT) 1816 return __glXError(GLXBadPixmap); 1817 1818 context = __glXForceCurrent(cl, req->contextTag, &error); 1819 if (!context) 1820 return error; 1821 1822 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1823 DixReadAccess, &pGlxDraw, &error)) 1824 return error; 1825 1826 if (!context->textureFromPixmap) 1827 return __glXError(GLXUnsupportedPrivateRequest); 1828 1829 return context->textureFromPixmap->bindTexImage(context, buffer, pGlxDraw); 1830} 1831 1832int 1833__glXDisp_ReleaseTexImageEXT(__GLXclientState * cl, GLbyte * pc) 1834{ 1835 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1836 ClientPtr client = cl->client; 1837 __GLXdrawable *pGlxDraw; 1838 __GLXcontext *context; 1839 GLXDrawable drawId; 1840 int buffer; 1841 int error; 1842 1843 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8); 1844 1845 pc += __GLX_VENDPRIV_HDR_SIZE; 1846 1847 drawId = *((CARD32 *) (pc)); 1848 buffer = *((INT32 *) (pc + 4)); 1849 1850 context = __glXForceCurrent(cl, req->contextTag, &error); 1851 if (!context) 1852 return error; 1853 1854 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1855 DixReadAccess, &pGlxDraw, &error)) 1856 return error; 1857 1858 if (!context->textureFromPixmap) 1859 return __glXError(GLXUnsupportedPrivateRequest); 1860 1861 return context->textureFromPixmap->releaseTexImage(context, 1862 buffer, pGlxDraw); 1863} 1864 1865int 1866__glXDisp_CopySubBufferMESA(__GLXclientState * cl, GLbyte * pc) 1867{ 1868 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1869 GLXContextTag tag = req->contextTag; 1870 __GLXcontext *glxc = NULL; 1871 __GLXdrawable *pGlxDraw; 1872 ClientPtr client = cl->client; 1873 GLXDrawable drawId; 1874 int error; 1875 int x, y, width, height; 1876 1877 (void) client; 1878 (void) req; 1879 1880 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20); 1881 1882 pc += __GLX_VENDPRIV_HDR_SIZE; 1883 1884 drawId = *((CARD32 *) (pc)); 1885 x = *((INT32 *) (pc + 4)); 1886 y = *((INT32 *) (pc + 8)); 1887 width = *((INT32 *) (pc + 12)); 1888 height = *((INT32 *) (pc + 16)); 1889 1890 if (tag) { 1891 glxc = __glXLookupContextByTag(cl, tag); 1892 if (!glxc) { 1893 return __glXError(GLXBadContextTag); 1894 } 1895 /* 1896 ** The calling thread is swapping its current drawable. In this case, 1897 ** glxSwapBuffers is in both GL and X streams, in terms of 1898 ** sequentiality. 1899 */ 1900 if (__glXForceCurrent(cl, tag, &error)) { 1901 /* 1902 ** Do whatever is needed to make sure that all preceding requests 1903 ** in both streams are completed before the swap is executed. 1904 */ 1905 glFinish(); 1906 glxc->hasUnflushedCommands = GL_FALSE; 1907 } 1908 else { 1909 return error; 1910 } 1911 } 1912 1913 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1914 if (!pGlxDraw) 1915 return error; 1916 1917 if (pGlxDraw == NULL || 1918 pGlxDraw->type != GLX_DRAWABLE_WINDOW || 1919 pGlxDraw->copySubBuffer == NULL) 1920 return __glXError(GLXBadDrawable); 1921 1922 (*pGlxDraw->copySubBuffer) (pGlxDraw, x, y, width, height); 1923 1924 return Success; 1925} 1926 1927/* hack for old glxext.h */ 1928#ifndef GLX_STEREO_TREE_EXT 1929#define GLX_STEREO_TREE_EXT 0x20F5 1930#endif 1931 1932/* 1933** Get drawable attributes 1934*/ 1935static int 1936DoGetDrawableAttributes(__GLXclientState * cl, XID drawId) 1937{ 1938 ClientPtr client = cl->client; 1939 xGLXGetDrawableAttributesReply reply; 1940 __GLXdrawable *pGlxDraw = NULL; 1941 DrawablePtr pDraw; 1942 CARD32 attributes[18]; 1943 int num = 0, error; 1944 1945 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, 1946 DixGetAttrAccess, &pGlxDraw, &error)) { 1947 /* hack for GLX 1.2 naked windows */ 1948 int err = dixLookupWindow((WindowPtr *)&pDraw, drawId, client, 1949 DixGetAttrAccess); 1950 if (err != Success) 1951 return error; 1952 } 1953 if (pGlxDraw) 1954 pDraw = pGlxDraw->pDraw; 1955 1956#define ATTRIB(a, v) do { \ 1957 attributes[2*num] = (a); \ 1958 attributes[2*num+1] = (v); \ 1959 num++; \ 1960 } while (0) 1961 1962 ATTRIB(GLX_Y_INVERTED_EXT, GL_FALSE); 1963 ATTRIB(GLX_WIDTH, pDraw->width); 1964 ATTRIB(GLX_HEIGHT, pDraw->height); 1965 ATTRIB(GLX_SCREEN, pDraw->pScreen->myNum); 1966 if (pGlxDraw) { 1967 ATTRIB(GLX_TEXTURE_TARGET_EXT, 1968 pGlxDraw->target == GL_TEXTURE_2D ? 1969 GLX_TEXTURE_2D_EXT : GLX_TEXTURE_RECTANGLE_EXT); 1970 ATTRIB(GLX_EVENT_MASK, pGlxDraw->eventMask); 1971 ATTRIB(GLX_FBCONFIG_ID, pGlxDraw->config->fbconfigID); 1972 if (pGlxDraw->type == GLX_DRAWABLE_PBUFFER) { 1973 ATTRIB(GLX_PRESERVED_CONTENTS, GL_TRUE); 1974 } 1975 if (pGlxDraw->type == GLX_DRAWABLE_WINDOW) { 1976 ATTRIB(GLX_STEREO_TREE_EXT, 0); 1977 } 1978 } 1979#undef ATTRIB 1980 1981 reply = (xGLXGetDrawableAttributesReply) { 1982 .type = X_Reply, 1983 .sequenceNumber = client->sequence, 1984 .length = num << 1, 1985 .numAttribs = num 1986 }; 1987 1988 if (client->swapped) { 1989 __glXSwapGetDrawableAttributesReply(client, &reply, attributes); 1990 } 1991 else { 1992 WriteToClient(client, sz_xGLXGetDrawableAttributesReply, &reply); 1993 WriteToClient(client, reply.length * sizeof(CARD32), attributes); 1994 } 1995 1996 return Success; 1997} 1998 1999int 2000__glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc) 2001{ 2002 ClientPtr client = cl->client; 2003 xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc; 2004 2005 /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */ 2006 REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq); 2007 2008 return DoGetDrawableAttributes(cl, req->drawable); 2009} 2010 2011int 2012__glXDisp_GetDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc) 2013{ 2014 ClientPtr client = cl->client; 2015 xGLXGetDrawableAttributesSGIXReq *req = 2016 (xGLXGetDrawableAttributesSGIXReq *) pc; 2017 2018 REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq); 2019 2020 return DoGetDrawableAttributes(cl, req->drawable); 2021} 2022 2023/************************************************************************/ 2024 2025/* 2026** Render and Renderlarge are not in the GLX API. They are used by the GLX 2027** client library to send batches of GL rendering commands. 2028*/ 2029 2030/* 2031** Execute all the drawing commands in a request. 2032*/ 2033int 2034__glXDisp_Render(__GLXclientState * cl, GLbyte * pc) 2035{ 2036 xGLXRenderReq *req; 2037 ClientPtr client = cl->client; 2038 int left, cmdlen, error; 2039 int commandsDone; 2040 CARD16 opcode; 2041 __GLXrenderHeader *hdr; 2042 __GLXcontext *glxc; 2043 2044 __GLX_DECLARE_SWAP_VARIABLES; 2045 2046 REQUEST_AT_LEAST_SIZE(xGLXRenderReq); 2047 2048 req = (xGLXRenderReq *) pc; 2049 if (client->swapped) { 2050 __GLX_SWAP_SHORT(&req->length); 2051 __GLX_SWAP_INT(&req->contextTag); 2052 } 2053 2054 glxc = __glXForceCurrent(cl, req->contextTag, &error); 2055 if (!glxc) { 2056 return error; 2057 } 2058 2059 commandsDone = 0; 2060 pc += sz_xGLXRenderReq; 2061 left = (req->length << 2) - sz_xGLXRenderReq; 2062 while (left > 0) { 2063 __GLXrenderSizeData entry; 2064 int extra = 0; 2065 __GLXdispatchRenderProcPtr proc; 2066 int err; 2067 2068 if (left < sizeof(__GLXrenderHeader)) 2069 return BadLength; 2070 2071 /* 2072 ** Verify that the header length and the overall length agree. 2073 ** Also, each command must be word aligned. 2074 */ 2075 hdr = (__GLXrenderHeader *) pc; 2076 if (client->swapped) { 2077 __GLX_SWAP_SHORT(&hdr->length); 2078 __GLX_SWAP_SHORT(&hdr->opcode); 2079 } 2080 cmdlen = hdr->length; 2081 opcode = hdr->opcode; 2082 2083 if (left < cmdlen) 2084 return BadLength; 2085 2086 /* 2087 ** Check for core opcodes and grab entry data. 2088 */ 2089 err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry); 2090 proc = (__GLXdispatchRenderProcPtr) 2091 __glXGetProtocolDecodeFunction(&Render_dispatch_info, 2092 opcode, client->swapped); 2093 2094 if ((err < 0) || (proc == NULL)) { 2095 client->errorValue = commandsDone; 2096 return __glXError(GLXBadRenderRequest); 2097 } 2098 2099 if (cmdlen < entry.bytes) { 2100 return BadLength; 2101 } 2102 2103 if (entry.varsize) { 2104 /* variable size command */ 2105 extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE, 2106 client->swapped, 2107 left - __GLX_RENDER_HDR_SIZE); 2108 if (extra < 0) { 2109 return BadLength; 2110 } 2111 } 2112 2113 if (cmdlen != safe_pad(safe_add(entry.bytes, extra))) { 2114 return BadLength; 2115 } 2116 2117 /* 2118 ** Skip over the header and execute the command. We allow the 2119 ** caller to trash the command memory. This is useful especially 2120 ** for things that require double alignment - they can just shift 2121 ** the data towards lower memory (trashing the header) by 4 bytes 2122 ** and achieve the required alignment. 2123 */ 2124 (*proc) (pc + __GLX_RENDER_HDR_SIZE); 2125 pc += cmdlen; 2126 left -= cmdlen; 2127 commandsDone++; 2128 } 2129 glxc->hasUnflushedCommands = GL_TRUE; 2130 return Success; 2131} 2132 2133/* 2134** Execute a large rendering request (one that spans multiple X requests). 2135*/ 2136int 2137__glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) 2138{ 2139 xGLXRenderLargeReq *req; 2140 ClientPtr client = cl->client; 2141 size_t dataBytes; 2142 __GLXrenderLargeHeader *hdr; 2143 __GLXcontext *glxc; 2144 int error; 2145 CARD16 opcode; 2146 2147 __GLX_DECLARE_SWAP_VARIABLES; 2148 2149 REQUEST_AT_LEAST_SIZE(xGLXRenderLargeReq); 2150 2151 req = (xGLXRenderLargeReq *) pc; 2152 if (client->swapped) { 2153 __GLX_SWAP_SHORT(&req->length); 2154 __GLX_SWAP_INT(&req->contextTag); 2155 __GLX_SWAP_INT(&req->dataBytes); 2156 __GLX_SWAP_SHORT(&req->requestNumber); 2157 __GLX_SWAP_SHORT(&req->requestTotal); 2158 } 2159 2160 glxc = __glXForceCurrent(cl, req->contextTag, &error); 2161 if (!glxc) { 2162 /* Reset in case this isn't 1st request. */ 2163 __glXResetLargeCommandStatus(cl); 2164 return error; 2165 } 2166 if (safe_pad(req->dataBytes) < 0) 2167 return BadLength; 2168 dataBytes = req->dataBytes; 2169 2170 /* 2171 ** Check the request length. 2172 */ 2173 if ((req->length << 2) != safe_pad(dataBytes) + sz_xGLXRenderLargeReq) { 2174 client->errorValue = req->length; 2175 /* Reset in case this isn't 1st request. */ 2176 __glXResetLargeCommandStatus(cl); 2177 return BadLength; 2178 } 2179 pc += sz_xGLXRenderLargeReq; 2180 2181 if (cl->largeCmdRequestsSoFar == 0) { 2182 __GLXrenderSizeData entry; 2183 int extra = 0; 2184 int left = (req->length << 2) - sz_xGLXRenderLargeReq; 2185 int cmdlen; 2186 int err; 2187 2188 /* 2189 ** This is the first request of a multi request command. 2190 ** Make enough space in the buffer, then copy the entire request. 2191 */ 2192 if (req->requestNumber != 1) { 2193 client->errorValue = req->requestNumber; 2194 return __glXError(GLXBadLargeRequest); 2195 } 2196 2197 if (dataBytes < __GLX_RENDER_LARGE_HDR_SIZE) 2198 return BadLength; 2199 2200 hdr = (__GLXrenderLargeHeader *) pc; 2201 if (client->swapped) { 2202 __GLX_SWAP_INT(&hdr->length); 2203 __GLX_SWAP_INT(&hdr->opcode); 2204 } 2205 opcode = hdr->opcode; 2206 if ((cmdlen = safe_pad(hdr->length)) < 0) 2207 return BadLength; 2208 2209 /* 2210 ** Check for core opcodes and grab entry data. 2211 */ 2212 err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry); 2213 if (err < 0) { 2214 client->errorValue = opcode; 2215 return __glXError(GLXBadLargeRequest); 2216 } 2217 2218 if (entry.varsize) { 2219 /* 2220 ** If it's a variable-size command (a command whose length must 2221 ** be computed from its parameters), all the parameters needed 2222 ** will be in the 1st request, so it's okay to do this. 2223 */ 2224 extra = (*entry.varsize) (pc + __GLX_RENDER_LARGE_HDR_SIZE, 2225 client->swapped, 2226 left - __GLX_RENDER_LARGE_HDR_SIZE); 2227 if (extra < 0) { 2228 return BadLength; 2229 } 2230 } 2231 2232 /* the +4 is safe because we know entry.bytes is small */ 2233 if (cmdlen != safe_pad(safe_add(entry.bytes + 4, extra))) { 2234 return BadLength; 2235 } 2236 2237 /* 2238 ** Make enough space in the buffer, then copy the entire request. 2239 */ 2240 if (cl->largeCmdBufSize < cmdlen) { 2241 GLbyte *newbuf = cl->largeCmdBuf; 2242 2243 if (!(newbuf = realloc(newbuf, cmdlen))) 2244 return BadAlloc; 2245 2246 cl->largeCmdBuf = newbuf; 2247 cl->largeCmdBufSize = cmdlen; 2248 } 2249 memcpy(cl->largeCmdBuf, pc, dataBytes); 2250 2251 cl->largeCmdBytesSoFar = dataBytes; 2252 cl->largeCmdBytesTotal = cmdlen; 2253 cl->largeCmdRequestsSoFar = 1; 2254 cl->largeCmdRequestsTotal = req->requestTotal; 2255 return Success; 2256 2257 } 2258 else { 2259 /* 2260 ** We are receiving subsequent (i.e. not the first) requests of a 2261 ** multi request command. 2262 */ 2263 int bytesSoFar; /* including this packet */ 2264 2265 /* 2266 ** Check the request number and the total request count. 2267 */ 2268 if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) { 2269 client->errorValue = req->requestNumber; 2270 __glXResetLargeCommandStatus(cl); 2271 return __glXError(GLXBadLargeRequest); 2272 } 2273 if (req->requestTotal != cl->largeCmdRequestsTotal) { 2274 client->errorValue = req->requestTotal; 2275 __glXResetLargeCommandStatus(cl); 2276 return __glXError(GLXBadLargeRequest); 2277 } 2278 2279 /* 2280 ** Check that we didn't get too much data. 2281 */ 2282 if ((bytesSoFar = safe_add(cl->largeCmdBytesSoFar, dataBytes)) < 0) { 2283 client->errorValue = dataBytes; 2284 __glXResetLargeCommandStatus(cl); 2285 return __glXError(GLXBadLargeRequest); 2286 } 2287 2288 if (bytesSoFar > cl->largeCmdBytesTotal) { 2289 client->errorValue = dataBytes; 2290 __glXResetLargeCommandStatus(cl); 2291 return __glXError(GLXBadLargeRequest); 2292 } 2293 2294 memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes); 2295 cl->largeCmdBytesSoFar += dataBytes; 2296 cl->largeCmdRequestsSoFar++; 2297 2298 if (req->requestNumber == cl->largeCmdRequestsTotal) { 2299 __GLXdispatchRenderProcPtr proc; 2300 2301 /* 2302 ** This is the last request; it must have enough bytes to complete 2303 ** the command. 2304 */ 2305 /* NOTE: the pad macro below is needed because the client library 2306 ** pads the total byte count, but not the per-request byte counts. 2307 ** The Protocol Encoding says the total byte count should not be 2308 ** padded, so a proposal will be made to the ARB to relax the 2309 ** padding constraint on the total byte count, thus preserving 2310 ** backward compatibility. Meanwhile, the padding done below 2311 ** fixes a bug that did not allow large commands of odd sizes to 2312 ** be accepted by the server. 2313 */ 2314 if (safe_pad(cl->largeCmdBytesSoFar) != cl->largeCmdBytesTotal) { 2315 client->errorValue = dataBytes; 2316 __glXResetLargeCommandStatus(cl); 2317 return __glXError(GLXBadLargeRequest); 2318 } 2319 hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf; 2320 /* 2321 ** The opcode and length field in the header had already been 2322 ** swapped when the first request was received. 2323 ** 2324 ** Use the opcode to index into the procedure table. 2325 */ 2326 opcode = hdr->opcode; 2327 2328 proc = (__GLXdispatchRenderProcPtr) 2329 __glXGetProtocolDecodeFunction(&Render_dispatch_info, opcode, 2330 client->swapped); 2331 if (proc == NULL) { 2332 client->errorValue = opcode; 2333 return __glXError(GLXBadLargeRequest); 2334 } 2335 2336 /* 2337 ** Skip over the header and execute the command. 2338 */ 2339 (*proc) (cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE); 2340 glxc->hasUnflushedCommands = GL_TRUE; 2341 2342 /* 2343 ** Reset for the next RenderLarge series. 2344 */ 2345 __glXResetLargeCommandStatus(cl); 2346 } 2347 else { 2348 /* 2349 ** This is neither the first nor the last request. 2350 */ 2351 } 2352 return Success; 2353 } 2354} 2355 2356/************************************************************************/ 2357 2358/* 2359** No support is provided for the vendor-private requests other than 2360** allocating the entry points in the dispatch table. 2361*/ 2362 2363int 2364__glXDisp_VendorPrivate(__GLXclientState * cl, GLbyte * pc) 2365{ 2366 ClientPtr client = cl->client; 2367 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2368 GLint vendorcode = req->vendorCode; 2369 __GLXdispatchVendorPrivProcPtr proc; 2370 2371 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2372 2373 proc = (__GLXdispatchVendorPrivProcPtr) 2374 __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, 2375 vendorcode, 0); 2376 if (proc != NULL) { 2377 (*proc) (cl, (GLbyte *) req); 2378 return Success; 2379 } 2380 2381 cl->client->errorValue = req->vendorCode; 2382 return __glXError(GLXUnsupportedPrivateRequest); 2383} 2384 2385int 2386__glXDisp_VendorPrivateWithReply(__GLXclientState * cl, GLbyte * pc) 2387{ 2388 ClientPtr client = cl->client; 2389 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2390 GLint vendorcode = req->vendorCode; 2391 __GLXdispatchVendorPrivProcPtr proc; 2392 2393 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2394 2395 proc = (__GLXdispatchVendorPrivProcPtr) 2396 __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, 2397 vendorcode, 0); 2398 if (proc != NULL) { 2399 return (*proc) (cl, (GLbyte *) req); 2400 } 2401 2402 cl->client->errorValue = vendorcode; 2403 return __glXError(GLXUnsupportedPrivateRequest); 2404} 2405 2406int 2407__glXDisp_QueryExtensionsString(__GLXclientState * cl, GLbyte * pc) 2408{ 2409 ClientPtr client = cl->client; 2410 xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; 2411 xGLXQueryExtensionsStringReply reply; 2412 __GLXscreen *pGlxScreen; 2413 size_t n, length; 2414 char *buf; 2415 int err; 2416 2417 REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq); 2418 2419 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2420 return err; 2421 2422 n = strlen(pGlxScreen->GLXextensions) + 1; 2423 length = __GLX_PAD(n) >> 2; 2424 reply = (xGLXQueryExtensionsStringReply) { 2425 .type = X_Reply, 2426 .sequenceNumber = client->sequence, 2427 .length = length, 2428 .n = n 2429 }; 2430 2431 /* Allocate buffer to make sure it's a multiple of 4 bytes big. */ 2432 buf = calloc(length, 4); 2433 if (buf == NULL) 2434 return BadAlloc; 2435 memcpy(buf, pGlxScreen->GLXextensions, n); 2436 2437 if (client->swapped) { 2438 glxSwapQueryExtensionsStringReply(client, &reply, buf); 2439 } 2440 else { 2441 WriteToClient(client, sz_xGLXQueryExtensionsStringReply, &reply); 2442 WriteToClient(client, (int) (length << 2), buf); 2443 } 2444 2445 free(buf); 2446 return Success; 2447} 2448 2449int 2450__glXDisp_QueryServerString(__GLXclientState * cl, GLbyte * pc) 2451{ 2452 ClientPtr client = cl->client; 2453 xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; 2454 xGLXQueryServerStringReply reply; 2455 size_t n, length; 2456 const char *ptr; 2457 char *buf; 2458 __GLXscreen *pGlxScreen; 2459 int err; 2460 char ver_str[16]; 2461 2462 REQUEST_SIZE_MATCH(xGLXQueryServerStringReq); 2463 2464 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2465 return err; 2466 2467 switch (req->name) { 2468 case GLX_VENDOR: 2469 ptr = GLXServerVendorName; 2470 break; 2471 case GLX_VERSION: 2472 /* Return to the server version rather than the screen version 2473 * to prevent confusion when they do not match. 2474 */ 2475 snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion); 2476 ptr = ver_str; 2477 break; 2478 case GLX_EXTENSIONS: 2479 ptr = pGlxScreen->GLXextensions; 2480 break; 2481 default: 2482 return BadValue; 2483 } 2484 2485 n = strlen(ptr) + 1; 2486 length = __GLX_PAD(n) >> 2; 2487 reply = (xGLXQueryServerStringReply) { 2488 .type = X_Reply, 2489 .sequenceNumber = client->sequence, 2490 .length = length, 2491 .n = n 2492 }; 2493 2494 buf = calloc(length, 4); 2495 if (buf == NULL) { 2496 return BadAlloc; 2497 } 2498 memcpy(buf, ptr, n); 2499 2500 if (client->swapped) { 2501 glxSwapQueryServerStringReply(client, &reply, buf); 2502 } 2503 else { 2504 WriteToClient(client, sz_xGLXQueryServerStringReply, &reply); 2505 WriteToClient(client, (int) (length << 2), buf); 2506 } 2507 2508 free(buf); 2509 return Success; 2510} 2511 2512int 2513__glXDisp_ClientInfo(__GLXclientState * cl, GLbyte * pc) 2514{ 2515 ClientPtr client = cl->client; 2516 xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; 2517 const char *buf; 2518 2519 REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq); 2520 2521 buf = (const char *) (req + 1); 2522 if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq))) 2523 return BadLength; 2524 2525 free(cl->GLClientextensions); 2526 cl->GLClientextensions = strdup(buf); 2527 2528 return Success; 2529} 2530 2531#include <GL/glxtokens.h> 2532 2533void 2534__glXsendSwapEvent(__GLXdrawable *drawable, int type, CARD64 ust, 2535 CARD64 msc, CARD32 sbc) 2536{ 2537 ClientPtr client = clients[CLIENT_ID(drawable->drawId)]; 2538 2539 xGLXBufferSwapComplete2 wire = { 2540 .type = __glXEventBase + GLX_BufferSwapComplete 2541 }; 2542 2543 if (!client) 2544 return; 2545 2546 if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) 2547 return; 2548 2549 wire.event_type = type; 2550 wire.drawable = drawable->drawId; 2551 wire.ust_hi = ust >> 32; 2552 wire.ust_lo = ust & 0xffffffff; 2553 wire.msc_hi = msc >> 32; 2554 wire.msc_lo = msc & 0xffffffff; 2555 wire.sbc = sbc; 2556 2557 WriteEventsToClient(client, 1, (xEvent *) &wire); 2558} 2559 2560#if PRESENT 2561static void 2562__glXpresentCompleteNotify(WindowPtr window, CARD8 present_kind, CARD8 present_mode, 2563 CARD32 serial, uint64_t ust, uint64_t msc) 2564{ 2565 __GLXdrawable *drawable; 2566 int glx_type; 2567 int rc; 2568 2569 if (present_kind != PresentCompleteKindPixmap) 2570 return; 2571 2572 rc = dixLookupResourceByType((void **) &drawable, window->drawable.id, 2573 __glXDrawableRes, serverClient, DixGetAttrAccess); 2574 2575 if (rc != Success) 2576 return; 2577 2578 if (present_mode == PresentCompleteModeFlip) 2579 glx_type = GLX_FLIP_COMPLETE_INTEL; 2580 else 2581 glx_type = GLX_BLIT_COMPLETE_INTEL; 2582 2583 __glXsendSwapEvent(drawable, glx_type, ust, msc, serial); 2584} 2585 2586#include <present.h> 2587 2588void 2589__glXregisterPresentCompleteNotify(void) 2590{ 2591 present_register_complete_notify(__glXpresentCompleteNotify); 2592} 2593#endif 2594