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