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