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