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