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