glxcmds.c revision 65b04b38
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->config = config; 1099 drawable->eventMask = 0; 1100 1101 return GL_TRUE; 1102} 1103 1104void 1105__glXDrawableRelease(__GLXdrawable *drawable) 1106{ 1107} 1108 1109static int 1110DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, 1111 __GLXconfig *config, DrawablePtr pDraw, XID drawableId, 1112 XID glxDrawableId, int type) 1113{ 1114 __GLXdrawable *pGlxDraw; 1115 1116 if (pGlxScreen->pScreen != pDraw->pScreen) 1117 return BadMatch; 1118 1119 pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw, 1120 drawableId, type, 1121 glxDrawableId, config); 1122 if (pGlxDraw == NULL) 1123 return BadAlloc; 1124 1125 if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) { 1126 pGlxDraw->destroy (pGlxDraw); 1127 return BadAlloc; 1128 } 1129 1130 /* 1131 * Windows aren't refcounted, so track both the X and the GLX window 1132 * so we get called regardless of destruction order. 1133 */ 1134 if (drawableId != glxDrawableId && type == GLX_DRAWABLE_WINDOW && 1135 !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { 1136 pGlxDraw->destroy (pGlxDraw); 1137 return BadAlloc; 1138 } 1139 1140 return Success; 1141} 1142 1143static int 1144DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config, 1145 XID drawableId, XID glxDrawableId) 1146{ 1147 DrawablePtr pDraw; 1148 int err; 1149 1150 LEGAL_NEW_RESOURCE(glxDrawableId, client); 1151 1152 err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess); 1153 if (err != Success) { 1154 client->errorValue = drawableId; 1155 return err; 1156 } 1157 if (pDraw->type != DRAWABLE_PIXMAP) { 1158 client->errorValue = drawableId; 1159 return BadPixmap; 1160 } 1161 1162 err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, 1163 glxDrawableId, GLX_DRAWABLE_PIXMAP); 1164 1165 ((PixmapPtr)pDraw)->refcnt++; 1166 1167 return err; 1168} 1169 1170static void 1171determineTextureTarget(ClientPtr client, XID glxDrawableID, 1172 CARD32 *attribs, CARD32 numAttribs) 1173{ 1174 GLenum target = 0; 1175 GLenum format = 0; 1176 int i, err; 1177 __GLXdrawable *pGlxDraw; 1178 1179 if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP, 1180 DixWriteAccess, &pGlxDraw, &err)) 1181 /* We just added it in CreatePixmap, so we should never get here. */ 1182 return; 1183 1184 for (i = 0; i < numAttribs; i++) { 1185 if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { 1186 switch (attribs[2 * i + 1]) { 1187 case GLX_TEXTURE_2D_EXT: 1188 target = GL_TEXTURE_2D; 1189 break; 1190 case GLX_TEXTURE_RECTANGLE_EXT: 1191 target = GL_TEXTURE_RECTANGLE_ARB; 1192 break; 1193 } 1194 } 1195 1196 if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT) 1197 format = attribs[2 * i + 1]; 1198 } 1199 1200 if (!target) { 1201 int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height; 1202 1203 if (h & (h - 1) || w & (w - 1)) 1204 target = GL_TEXTURE_RECTANGLE_ARB; 1205 else 1206 target = GL_TEXTURE_2D; 1207 } 1208 1209 pGlxDraw->target = target; 1210 pGlxDraw->format = format; 1211} 1212 1213int __glXDisp_CreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) 1214{ 1215 ClientPtr client = cl->client; 1216 xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; 1217 __GLXconfig *config; 1218 __GLXscreen *pGlxScreen; 1219 int err; 1220 1221 REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq); 1222 1223 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1224 return err; 1225 if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) 1226 return err; 1227 1228 return DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1229 req->pixmap, req->glxpixmap); 1230} 1231 1232int __glXDisp_CreatePixmap(__GLXclientState *cl, GLbyte *pc) 1233{ 1234 ClientPtr client = cl->client; 1235 xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; 1236 __GLXconfig *config; 1237 __GLXscreen *pGlxScreen; 1238 int err; 1239 1240 REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq); 1241 if (req->numAttribs > (UINT32_MAX >> 3)) { 1242 client->errorValue = req->numAttribs; 1243 return BadValue; 1244 } 1245 REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3); 1246 1247 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1248 return err; 1249 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1250 return err; 1251 1252 err = DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1253 req->pixmap, req->glxpixmap); 1254 if (err != Success) 1255 return err; 1256 1257 determineTextureTarget(cl->client, req->glxpixmap, 1258 (CARD32*) (req + 1), req->numAttribs); 1259 1260 return Success; 1261} 1262 1263int __glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) 1264{ 1265 ClientPtr client = cl->client; 1266 xGLXCreateGLXPixmapWithConfigSGIXReq *req = 1267 (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; 1268 __GLXconfig *config; 1269 __GLXscreen *pGlxScreen; 1270 int err; 1271 1272 REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq); 1273 1274 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1275 return err; 1276 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1277 return err; 1278 1279 return DoCreateGLXPixmap(cl->client, pGlxScreen, 1280 config, req->pixmap, req->glxpixmap); 1281} 1282 1283 1284static int DoDestroyDrawable(__GLXclientState *cl, XID glxdrawable, int type) 1285{ 1286 __GLXdrawable *pGlxDraw; 1287 int err; 1288 1289 if (!validGlxDrawable(cl->client, glxdrawable, type, 1290 DixDestroyAccess, &pGlxDraw, &err)) 1291 return err; 1292 1293 FreeResource(glxdrawable, FALSE); 1294 1295 return Success; 1296} 1297 1298int __glXDisp_DestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) 1299{ 1300 ClientPtr client = cl->client; 1301 xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; 1302 1303 REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq); 1304 1305 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1306} 1307 1308int __glXDisp_DestroyPixmap(__GLXclientState *cl, GLbyte *pc) 1309{ 1310 ClientPtr client = cl->client; 1311 xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; 1312 1313 /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set 1314 * length to 3 instead of 2 */ 1315 REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq); 1316 1317 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1318} 1319 1320static int 1321DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, 1322 int width, int height, XID glxDrawableId) 1323{ 1324 __GLXconfig *config; 1325 __GLXscreen *pGlxScreen; 1326 PixmapPtr pPixmap; 1327 int err; 1328 1329 LEGAL_NEW_RESOURCE(glxDrawableId, client); 1330 1331 if (!validGlxScreen(client, screenNum, &pGlxScreen, &err)) 1332 return err; 1333 if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err)) 1334 return err; 1335 1336 __glXenterServer(GL_FALSE); 1337 pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen, 1338 width, height, config->rgbBits, 0); 1339 __glXleaveServer(GL_FALSE); 1340 1341 /* Assign the pixmap the same id as the pbuffer and add it as a 1342 * resource so it and the DRI2 drawable will be reclaimed when the 1343 * pbuffer is destroyed. */ 1344 pPixmap->drawable.id = glxDrawableId; 1345 if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap)) 1346 return BadAlloc; 1347 1348 return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, 1349 glxDrawableId, glxDrawableId, 1350 GLX_DRAWABLE_PBUFFER); 1351} 1352 1353int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) 1354{ 1355 ClientPtr client = cl->client; 1356 xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; 1357 CARD32 *attrs; 1358 int width, height, i; 1359 1360 REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq); 1361 if (req->numAttribs > (UINT32_MAX >> 3)) { 1362 client->errorValue = req->numAttribs; 1363 return BadValue; 1364 } 1365 REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3); 1366 1367 attrs = (CARD32 *) (req + 1); 1368 width = 0; 1369 height = 0; 1370 1371 for (i = 0; i < req->numAttribs; i++) { 1372 switch (attrs[i * 2]) { 1373 case GLX_PBUFFER_WIDTH: 1374 width = attrs[i * 2 + 1]; 1375 break; 1376 case GLX_PBUFFER_HEIGHT: 1377 height = attrs[i * 2 + 1]; 1378 break; 1379 case GLX_LARGEST_PBUFFER: 1380 case GLX_PRESERVED_CONTENTS: 1381 /* FIXME: huh... */ 1382 break; 1383 } 1384 } 1385 1386 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1387 width, height, req->pbuffer); 1388} 1389 1390int __glXDisp_CreateGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) 1391{ 1392 ClientPtr client = cl->client; 1393 xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; 1394 1395 REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq); 1396 1397 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1398 req->width, req->height, req->pbuffer); 1399} 1400 1401int __glXDisp_DestroyPbuffer(__GLXclientState *cl, GLbyte *pc) 1402{ 1403 ClientPtr client = cl->client; 1404 xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; 1405 1406 REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq); 1407 1408 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1409} 1410 1411int __glXDisp_DestroyGLXPbufferSGIX(__GLXclientState *cl, GLbyte *pc) 1412{ 1413 ClientPtr client = cl->client; 1414 xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc; 1415 1416 REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq); 1417 1418 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1419} 1420 1421static int 1422DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable, 1423 int numAttribs, CARD32 *attribs) 1424{ 1425 __GLXdrawable *pGlxDraw; 1426 int i, err; 1427 1428 if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY, 1429 DixSetAttrAccess, &pGlxDraw, &err)) 1430 return err; 1431 1432 for (i = 0; i < numAttribs; i++) { 1433 switch(attribs[i * 2]) { 1434 case GLX_EVENT_MASK: 1435 /* All we do is to record the event mask so we can send it 1436 * back when queried. We never actually clobber the 1437 * pbuffers, so we never need to send out the event. */ 1438 pGlxDraw->eventMask = attribs[i * 2 + 1]; 1439 break; 1440 } 1441 } 1442 1443 return Success; 1444} 1445 1446int __glXDisp_ChangeDrawableAttributes(__GLXclientState *cl, GLbyte *pc) 1447{ 1448 ClientPtr client = cl->client; 1449 xGLXChangeDrawableAttributesReq *req = 1450 (xGLXChangeDrawableAttributesReq *) pc; 1451 1452 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq); 1453 if (req->numAttribs > (UINT32_MAX >> 3)) { 1454 client->errorValue = req->numAttribs; 1455 return BadValue; 1456 } 1457#if 0 1458 /* mesa sends an additional 8 bytes */ 1459 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); 1460#else 1461 if (((sizeof(xGLXChangeDrawableAttributesReq) + (req->numAttribs << 3)) >> 2) < client->req_len) 1462 return BadLength; 1463#endif 1464 1465 return DoChangeDrawableAttributes(cl->client, req->drawable, 1466 req->numAttribs, (CARD32 *) (req + 1)); 1467} 1468 1469int __glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) 1470{ 1471 ClientPtr client = cl->client; 1472 xGLXChangeDrawableAttributesSGIXReq *req = 1473 (xGLXChangeDrawableAttributesSGIXReq *)pc; 1474 1475 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq); 1476 if (req->numAttribs > (UINT32_MAX >> 3)) { 1477 client->errorValue = req->numAttribs; 1478 return BadValue; 1479 } 1480 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, req->numAttribs << 3); 1481 1482 return DoChangeDrawableAttributes(cl->client, req->drawable, 1483 req->numAttribs, (CARD32 *) (req + 1)); 1484} 1485 1486int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) 1487{ 1488 xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; 1489 __GLXconfig *config; 1490 __GLXscreen *pGlxScreen; 1491 ClientPtr client = cl->client; 1492 DrawablePtr pDraw; 1493 int err; 1494 1495 REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq); 1496 if (req->numAttribs > (UINT32_MAX >> 3)) { 1497 client->errorValue = req->numAttribs; 1498 return BadValue; 1499 } 1500 REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3); 1501 1502 LEGAL_NEW_RESOURCE(req->glxwindow, client); 1503 1504 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 1505 return err; 1506 if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err)) 1507 return err; 1508 1509 err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess); 1510 if (err != Success || pDraw->type != DRAWABLE_WINDOW) { 1511 client->errorValue = req->window; 1512 return BadWindow; 1513 } 1514 1515 if (!validGlxFBConfigForWindow(client, config, pDraw, &err)) 1516 return err; 1517 1518 return DoCreateGLXDrawable(client, pGlxScreen, config, 1519 pDraw, req->window, 1520 req->glxwindow, GLX_DRAWABLE_WINDOW); 1521} 1522 1523int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) 1524{ 1525 ClientPtr client = cl->client; 1526 xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; 1527 1528 /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */ 1529 REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq); 1530 1531 return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); 1532} 1533 1534 1535/*****************************************************************************/ 1536 1537/* 1538** NOTE: There is no portable implementation for swap buffers as of 1539** this time that is of value. Consequently, this code must be 1540** implemented by somebody other than SGI. 1541*/ 1542int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) 1543{ 1544 ClientPtr client = cl->client; 1545 xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; 1546 GLXContextTag tag; 1547 XID drawId; 1548 __GLXcontext *glxc = NULL; 1549 __GLXdrawable *pGlxDraw; 1550 int error; 1551 1552 REQUEST_SIZE_MATCH(xGLXSwapBuffersReq); 1553 1554 tag = req->contextTag; 1555 drawId = req->drawable; 1556 if (tag) { 1557 glxc = __glXLookupContextByTag(cl, tag); 1558 if (!glxc) { 1559 return __glXError(GLXBadContextTag); 1560 } 1561 /* 1562 ** The calling thread is swapping its current drawable. In this case, 1563 ** glxSwapBuffers is in both GL and X streams, in terms of 1564 ** sequentiality. 1565 */ 1566 if (__glXForceCurrent(cl, tag, &error)) { 1567 /* 1568 ** Do whatever is needed to make sure that all preceding requests 1569 ** in both streams are completed before the swap is executed. 1570 */ 1571 CALL_Finish( GET_DISPATCH(), () ); 1572 __GLX_NOTE_FLUSHED_CMDS(glxc); 1573 } else { 1574 return error; 1575 } 1576 } 1577 1578 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1579 if (pGlxDraw == NULL) 1580 return error; 1581 1582 if (pGlxDraw->type == DRAWABLE_WINDOW && 1583 (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE) 1584 return __glXError(GLXBadDrawable); 1585 1586 return Success; 1587} 1588 1589 1590static int 1591DoQueryContext(__GLXclientState *cl, GLXContextID gcId) 1592{ 1593 ClientPtr client = cl->client; 1594 __GLXcontext *ctx; 1595 xGLXQueryContextInfoEXTReply reply; 1596 int nProps; 1597 int *sendBuf, *pSendBuf; 1598 int nReplyBytes; 1599 int err; 1600 1601 if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err)) 1602 return err; 1603 1604 nProps = 3; 1605 reply.length = nProps << 1; 1606 reply.type = X_Reply; 1607 reply.sequenceNumber = client->sequence; 1608 reply.n = nProps; 1609 1610 nReplyBytes = reply.length << 2; 1611 sendBuf = (int *)malloc((size_t)nReplyBytes); 1612 if (sendBuf == NULL) { 1613 return __glXError(GLXBadContext); /* XXX: Is this correct? */ 1614 } 1615 pSendBuf = sendBuf; 1616 *pSendBuf++ = GLX_SHARE_CONTEXT_EXT; 1617 *pSendBuf++ = (int)(ctx->share_id); 1618 *pSendBuf++ = GLX_VISUAL_ID_EXT; 1619 *pSendBuf++ = (int)(ctx->config->visualID); 1620 *pSendBuf++ = GLX_SCREEN_EXT; 1621 *pSendBuf++ = (int)(ctx->pGlxScreen->pScreen->myNum); 1622 1623 if (client->swapped) { 1624 __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf); 1625 } else { 1626 WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply); 1627 WriteToClient(client, nReplyBytes, (char *)sendBuf); 1628 } 1629 free((char *)sendBuf); 1630 1631 return Success; 1632} 1633 1634int __glXDisp_QueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) 1635{ 1636 ClientPtr client = cl->client; 1637 xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc; 1638 1639 REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq); 1640 1641 return DoQueryContext(cl, req->context); 1642} 1643 1644int __glXDisp_QueryContext(__GLXclientState *cl, GLbyte *pc) 1645{ 1646 ClientPtr client = cl->client; 1647 xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc; 1648 1649 REQUEST_SIZE_MATCH(xGLXQueryContextReq); 1650 1651 return DoQueryContext(cl, req->context); 1652} 1653 1654int __glXDisp_BindTexImageEXT(__GLXclientState *cl, GLbyte *pc) 1655{ 1656 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1657 ClientPtr client = cl->client; 1658 __GLXcontext *context; 1659 __GLXdrawable *pGlxDraw; 1660 GLXDrawable drawId; 1661 int buffer; 1662 int error; 1663 CARD32 num_attribs; 1664 1665 if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len) 1666 return BadLength; 1667 1668 pc += __GLX_VENDPRIV_HDR_SIZE; 1669 1670 drawId = *((CARD32 *) (pc)); 1671 buffer = *((INT32 *) (pc + 4)); 1672 num_attribs = *((CARD32 *) (pc + 8)); 1673 if (num_attribs > (UINT32_MAX >> 3)) { 1674 client->errorValue = num_attribs; 1675 return BadValue; 1676 } 1677 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3)); 1678 1679 if (buffer != GLX_FRONT_LEFT_EXT) 1680 return __glXError(GLXBadPixmap); 1681 1682 context = __glXForceCurrent (cl, req->contextTag, &error); 1683 if (!context) 1684 return error; 1685 1686 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1687 DixReadAccess, &pGlxDraw, &error)) 1688 return error; 1689 1690 if (!context->textureFromPixmap) 1691 return __glXError(GLXUnsupportedPrivateRequest); 1692 1693 return context->textureFromPixmap->bindTexImage(context, 1694 buffer, 1695 pGlxDraw); 1696} 1697 1698int __glXDisp_ReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc) 1699{ 1700 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1701 ClientPtr client = cl->client; 1702 __GLXdrawable *pGlxDraw; 1703 __GLXcontext *context; 1704 GLXDrawable drawId; 1705 int buffer; 1706 int error; 1707 1708 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8); 1709 1710 pc += __GLX_VENDPRIV_HDR_SIZE; 1711 1712 drawId = *((CARD32 *) (pc)); 1713 buffer = *((INT32 *) (pc + 4)); 1714 1715 context = __glXForceCurrent (cl, req->contextTag, &error); 1716 if (!context) 1717 return error; 1718 1719 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1720 DixReadAccess, &pGlxDraw, &error)) 1721 return error; 1722 1723 if (!context->textureFromPixmap) 1724 return __glXError(GLXUnsupportedPrivateRequest); 1725 1726 return context->textureFromPixmap->releaseTexImage(context, 1727 buffer, 1728 pGlxDraw); 1729} 1730 1731int __glXDisp_CopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) 1732{ 1733 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1734 GLXContextTag tag = req->contextTag; 1735 __GLXcontext *glxc = NULL; 1736 __GLXdrawable *pGlxDraw; 1737 ClientPtr client = cl->client; 1738 GLXDrawable drawId; 1739 int error; 1740 int x, y, width, height; 1741 1742 (void) client; 1743 (void) req; 1744 1745 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20); 1746 1747 pc += __GLX_VENDPRIV_HDR_SIZE; 1748 1749 drawId = *((CARD32 *) (pc)); 1750 x = *((INT32 *) (pc + 4)); 1751 y = *((INT32 *) (pc + 8)); 1752 width = *((INT32 *) (pc + 12)); 1753 height = *((INT32 *) (pc + 16)); 1754 1755 if (tag) { 1756 glxc = __glXLookupContextByTag(cl, tag); 1757 if (!glxc) { 1758 return __glXError(GLXBadContextTag); 1759 } 1760 /* 1761 ** The calling thread is swapping its current drawable. In this case, 1762 ** glxSwapBuffers is in both GL and X streams, in terms of 1763 ** sequentiality. 1764 */ 1765 if (__glXForceCurrent(cl, tag, &error)) { 1766 /* 1767 ** Do whatever is needed to make sure that all preceding requests 1768 ** in both streams are completed before the swap is executed. 1769 */ 1770 CALL_Finish( GET_DISPATCH(), () ); 1771 __GLX_NOTE_FLUSHED_CMDS(glxc); 1772 } else { 1773 return error; 1774 } 1775 } 1776 1777 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1778 if (!pGlxDraw) 1779 return error; 1780 1781 if (pGlxDraw == NULL || 1782 pGlxDraw->type != GLX_DRAWABLE_WINDOW || 1783 pGlxDraw->copySubBuffer == NULL) 1784 return __glXError(GLXBadDrawable); 1785 1786 (*pGlxDraw->copySubBuffer)(pGlxDraw, x, y, width, height); 1787 1788 return Success; 1789} 1790 1791/* 1792** Get drawable attributes 1793*/ 1794static int 1795DoGetDrawableAttributes(__GLXclientState *cl, XID drawId) 1796{ 1797 ClientPtr client = cl->client; 1798 xGLXGetDrawableAttributesReply reply; 1799 __GLXdrawable *pGlxDraw; 1800 CARD32 attributes[6]; 1801 int numAttribs, error; 1802 1803 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, 1804 DixGetAttrAccess, &pGlxDraw, &error)) 1805 return error; 1806 1807 numAttribs = 3; 1808 reply.length = numAttribs << 1; 1809 reply.type = X_Reply; 1810 reply.sequenceNumber = client->sequence; 1811 reply.numAttribs = numAttribs; 1812 1813 attributes[0] = GLX_TEXTURE_TARGET_EXT; 1814 attributes[1] = pGlxDraw->target == GL_TEXTURE_2D ? GLX_TEXTURE_2D_EXT : 1815 GLX_TEXTURE_RECTANGLE_EXT; 1816 attributes[2] = GLX_Y_INVERTED_EXT; 1817 attributes[3] = GL_FALSE; 1818 attributes[4] = GLX_EVENT_MASK; 1819 attributes[5] = pGlxDraw->eventMask; 1820 1821 if (client->swapped) { 1822 __glXSwapGetDrawableAttributesReply(client, &reply, attributes); 1823 } else { 1824 WriteToClient(client, sz_xGLXGetDrawableAttributesReply, 1825 (char *)&reply); 1826 WriteToClient(client, reply.length * sizeof (CARD32), 1827 (char *)attributes); 1828 } 1829 1830 return Success; 1831} 1832 1833int __glXDisp_GetDrawableAttributes(__GLXclientState *cl, GLbyte *pc) 1834{ 1835 ClientPtr client = cl->client; 1836 xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *)pc; 1837 1838 /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */ 1839 REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq); 1840 1841 return DoGetDrawableAttributes(cl, req->drawable); 1842} 1843 1844int __glXDisp_GetDrawableAttributesSGIX(__GLXclientState *cl, GLbyte *pc) 1845{ 1846 ClientPtr client = cl->client; 1847 xGLXGetDrawableAttributesSGIXReq *req = 1848 (xGLXGetDrawableAttributesSGIXReq *)pc; 1849 1850 REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq); 1851 1852 return DoGetDrawableAttributes(cl, req->drawable); 1853} 1854 1855/************************************************************************/ 1856 1857/* 1858** Render and Renderlarge are not in the GLX API. They are used by the GLX 1859** client library to send batches of GL rendering commands. 1860*/ 1861 1862/* 1863** Execute all the drawing commands in a request. 1864*/ 1865int __glXDisp_Render(__GLXclientState *cl, GLbyte *pc) 1866{ 1867 xGLXRenderReq *req; 1868 ClientPtr client= cl->client; 1869 int left, cmdlen, error; 1870 int commandsDone; 1871 CARD16 opcode; 1872 __GLXrenderHeader *hdr; 1873 __GLXcontext *glxc; 1874 __GLX_DECLARE_SWAP_VARIABLES; 1875 1876 REQUEST_AT_LEAST_SIZE(xGLXRenderReq); 1877 1878 req = (xGLXRenderReq *) pc; 1879 if (client->swapped) { 1880 __GLX_SWAP_SHORT(&req->length); 1881 __GLX_SWAP_INT(&req->contextTag); 1882 } 1883 1884 glxc = __glXForceCurrent(cl, req->contextTag, &error); 1885 if (!glxc) { 1886 return error; 1887 } 1888 1889 commandsDone = 0; 1890 pc += sz_xGLXRenderReq; 1891 left = (req->length << 2) - sz_xGLXRenderReq; 1892 while (left > 0) { 1893 __GLXrenderSizeData entry; 1894 int extra; 1895 __GLXdispatchRenderProcPtr proc; 1896 int err; 1897 1898 if (left < sizeof(__GLXrenderHeader)) 1899 return BadLength; 1900 1901 /* 1902 ** Verify that the header length and the overall length agree. 1903 ** Also, each command must be word aligned. 1904 */ 1905 hdr = (__GLXrenderHeader *) pc; 1906 if (client->swapped) { 1907 __GLX_SWAP_SHORT(&hdr->length); 1908 __GLX_SWAP_SHORT(&hdr->opcode); 1909 } 1910 cmdlen = hdr->length; 1911 opcode = hdr->opcode; 1912 1913 /* 1914 ** Check for core opcodes and grab entry data. 1915 */ 1916 err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry); 1917 proc = (__GLXdispatchRenderProcPtr) 1918 __glXGetProtocolDecodeFunction(& Render_dispatch_info, 1919 opcode, client->swapped); 1920 1921 if ((err < 0) || (proc == NULL)) { 1922 client->errorValue = commandsDone; 1923 return __glXError(GLXBadRenderRequest); 1924 } 1925 1926 if (entry.varsize) { 1927 /* variable size command */ 1928 extra = (*entry.varsize)(pc + __GLX_RENDER_HDR_SIZE, 1929 client->swapped); 1930 if (extra < 0) { 1931 extra = 0; 1932 } 1933 if (cmdlen != __GLX_PAD(entry.bytes + extra)) { 1934 return BadLength; 1935 } 1936 } else { 1937 /* constant size command */ 1938 if (cmdlen != __GLX_PAD(entry.bytes)) { 1939 return BadLength; 1940 } 1941 } 1942 if (left < cmdlen) { 1943 return BadLength; 1944 } 1945 1946 /* 1947 ** Skip over the header and execute the command. We allow the 1948 ** caller to trash the command memory. This is useful especially 1949 ** for things that require double alignment - they can just shift 1950 ** the data towards lower memory (trashing the header) by 4 bytes 1951 ** and achieve the required alignment. 1952 */ 1953 (*proc)(pc + __GLX_RENDER_HDR_SIZE); 1954 pc += cmdlen; 1955 left -= cmdlen; 1956 commandsDone++; 1957 } 1958 __GLX_NOTE_UNFLUSHED_CMDS(glxc); 1959 return Success; 1960} 1961 1962 1963/* 1964** Execute a large rendering request (one that spans multiple X requests). 1965*/ 1966int __glXDisp_RenderLarge(__GLXclientState *cl, GLbyte *pc) 1967{ 1968 xGLXRenderLargeReq *req; 1969 ClientPtr client= cl->client; 1970 size_t dataBytes; 1971 __GLXrenderLargeHeader *hdr; 1972 __GLXcontext *glxc; 1973 int error; 1974 CARD16 opcode; 1975 __GLX_DECLARE_SWAP_VARIABLES; 1976 1977 req = (xGLXRenderLargeReq *) pc; 1978 if (client->swapped) { 1979 __GLX_SWAP_SHORT(&req->length); 1980 __GLX_SWAP_INT(&req->contextTag); 1981 __GLX_SWAP_INT(&req->dataBytes); 1982 __GLX_SWAP_SHORT(&req->requestNumber); 1983 __GLX_SWAP_SHORT(&req->requestTotal); 1984 } 1985 1986 glxc = __glXForceCurrent(cl, req->contextTag, &error); 1987 if (!glxc) { 1988 /* Reset in case this isn't 1st request. */ 1989 __glXResetLargeCommandStatus(cl); 1990 return error; 1991 } 1992 dataBytes = req->dataBytes; 1993 1994 /* 1995 ** Check the request length. 1996 */ 1997 if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) { 1998 client->errorValue = req->length; 1999 /* Reset in case this isn't 1st request. */ 2000 __glXResetLargeCommandStatus(cl); 2001 return BadLength; 2002 } 2003 pc += sz_xGLXRenderLargeReq; 2004 2005 if (cl->largeCmdRequestsSoFar == 0) { 2006 __GLXrenderSizeData entry; 2007 int extra; 2008 size_t cmdlen; 2009 int err; 2010 2011 /* 2012 ** This is the first request of a multi request command. 2013 ** Make enough space in the buffer, then copy the entire request. 2014 */ 2015 if (req->requestNumber != 1) { 2016 client->errorValue = req->requestNumber; 2017 return __glXError(GLXBadLargeRequest); 2018 } 2019 2020 hdr = (__GLXrenderLargeHeader *) pc; 2021 if (client->swapped) { 2022 __GLX_SWAP_INT(&hdr->length); 2023 __GLX_SWAP_INT(&hdr->opcode); 2024 } 2025 cmdlen = hdr->length; 2026 opcode = hdr->opcode; 2027 2028 /* 2029 ** Check for core opcodes and grab entry data. 2030 */ 2031 err = __glXGetProtocolSizeData(& Render_dispatch_info, opcode, & entry); 2032 if (err < 0) { 2033 client->errorValue = opcode; 2034 return __glXError(GLXBadLargeRequest); 2035 } 2036 2037 if (entry.varsize) { 2038 /* 2039 ** If it's a variable-size command (a command whose length must 2040 ** be computed from its parameters), all the parameters needed 2041 ** will be in the 1st request, so it's okay to do this. 2042 */ 2043 extra = (*entry.varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE, 2044 client->swapped); 2045 if (extra < 0) { 2046 extra = 0; 2047 } 2048 /* large command's header is 4 bytes longer, so add 4 */ 2049 if (cmdlen != __GLX_PAD(entry.bytes + 4 + extra)) { 2050 return BadLength; 2051 } 2052 } else { 2053 /* constant size command */ 2054 if (cmdlen != __GLX_PAD(entry.bytes + 4)) { 2055 return BadLength; 2056 } 2057 } 2058 /* 2059 ** Make enough space in the buffer, then copy the entire request. 2060 */ 2061 if (cl->largeCmdBufSize < cmdlen) { 2062 if (!cl->largeCmdBuf) { 2063 cl->largeCmdBuf = (GLbyte *) malloc(cmdlen); 2064 } else { 2065 cl->largeCmdBuf = (GLbyte *) realloc(cl->largeCmdBuf, cmdlen); 2066 } 2067 if (!cl->largeCmdBuf) { 2068 return BadAlloc; 2069 } 2070 cl->largeCmdBufSize = cmdlen; 2071 } 2072 memcpy(cl->largeCmdBuf, pc, dataBytes); 2073 2074 cl->largeCmdBytesSoFar = dataBytes; 2075 cl->largeCmdBytesTotal = cmdlen; 2076 cl->largeCmdRequestsSoFar = 1; 2077 cl->largeCmdRequestsTotal = req->requestTotal; 2078 return Success; 2079 2080 } else { 2081 /* 2082 ** We are receiving subsequent (i.e. not the first) requests of a 2083 ** multi request command. 2084 */ 2085 2086 /* 2087 ** Check the request number and the total request count. 2088 */ 2089 if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) { 2090 client->errorValue = req->requestNumber; 2091 __glXResetLargeCommandStatus(cl); 2092 return __glXError(GLXBadLargeRequest); 2093 } 2094 if (req->requestTotal != cl->largeCmdRequestsTotal) { 2095 client->errorValue = req->requestTotal; 2096 __glXResetLargeCommandStatus(cl); 2097 return __glXError(GLXBadLargeRequest); 2098 } 2099 2100 /* 2101 ** Check that we didn't get too much data. 2102 */ 2103 if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) { 2104 client->errorValue = dataBytes; 2105 __glXResetLargeCommandStatus(cl); 2106 return __glXError(GLXBadLargeRequest); 2107 } 2108 memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes); 2109 cl->largeCmdBytesSoFar += dataBytes; 2110 cl->largeCmdRequestsSoFar++; 2111 2112 if (req->requestNumber == cl->largeCmdRequestsTotal) { 2113 __GLXdispatchRenderProcPtr proc; 2114 2115 /* 2116 ** This is the last request; it must have enough bytes to complete 2117 ** the command. 2118 */ 2119 /* NOTE: the two pad macros have been added below; they are needed 2120 ** because the client library pads the total byte count, but not 2121 ** the per-request byte counts. The Protocol Encoding says the 2122 ** total byte count should not be padded, so a proposal will be 2123 ** made to the ARB to relax the padding constraint on the total 2124 ** byte count, thus preserving backward compatibility. Meanwhile, 2125 ** the padding done below fixes a bug that did not allow 2126 ** large commands of odd sizes to be accepted by the server. 2127 */ 2128 if (__GLX_PAD(cl->largeCmdBytesSoFar) != 2129 __GLX_PAD(cl->largeCmdBytesTotal)) { 2130 client->errorValue = dataBytes; 2131 __glXResetLargeCommandStatus(cl); 2132 return __glXError(GLXBadLargeRequest); 2133 } 2134 hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf; 2135 /* 2136 ** The opcode and length field in the header had already been 2137 ** swapped when the first request was received. 2138 ** 2139 ** Use the opcode to index into the procedure table. 2140 */ 2141 opcode = hdr->opcode; 2142 2143 proc = (__GLXdispatchRenderProcPtr) 2144 __glXGetProtocolDecodeFunction(& Render_dispatch_info, opcode, 2145 client->swapped); 2146 if (proc == NULL) { 2147 client->errorValue = opcode; 2148 return __glXError(GLXBadLargeRequest); 2149 } 2150 2151 /* 2152 ** Skip over the header and execute the command. 2153 */ 2154 (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE); 2155 __GLX_NOTE_UNFLUSHED_CMDS(glxc); 2156 2157 /* 2158 ** Reset for the next RenderLarge series. 2159 */ 2160 __glXResetLargeCommandStatus(cl); 2161 } else { 2162 /* 2163 ** This is neither the first nor the last request. 2164 */ 2165 } 2166 return Success; 2167 } 2168} 2169 2170/************************************************************************/ 2171 2172/* 2173** No support is provided for the vendor-private requests other than 2174** allocating the entry points in the dispatch table. 2175*/ 2176 2177int __glXDisp_VendorPrivate(__GLXclientState *cl, GLbyte *pc) 2178{ 2179 ClientPtr client = cl->client; 2180 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2181 GLint vendorcode = req->vendorCode; 2182 __GLXdispatchVendorPrivProcPtr proc; 2183 2184 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2185 2186 proc = (__GLXdispatchVendorPrivProcPtr) 2187 __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info, 2188 vendorcode, 0); 2189 if (proc != NULL) { 2190 (*proc)(cl, (GLbyte*)req); 2191 return Success; 2192 } 2193 2194 cl->client->errorValue = req->vendorCode; 2195 return __glXError(GLXUnsupportedPrivateRequest); 2196} 2197 2198int __glXDisp_VendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc) 2199{ 2200 ClientPtr client = cl->client; 2201 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2202 GLint vendorcode = req->vendorCode; 2203 __GLXdispatchVendorPrivProcPtr proc; 2204 2205 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2206 2207 proc = (__GLXdispatchVendorPrivProcPtr) 2208 __glXGetProtocolDecodeFunction(& VendorPriv_dispatch_info, 2209 vendorcode, 0); 2210 if (proc != NULL) { 2211 return (*proc)(cl, (GLbyte*)req); 2212 } 2213 2214 cl->client->errorValue = vendorcode; 2215 return __glXError(GLXUnsupportedPrivateRequest); 2216} 2217 2218int __glXDisp_QueryExtensionsString(__GLXclientState *cl, GLbyte *pc) 2219{ 2220 ClientPtr client = cl->client; 2221 xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; 2222 xGLXQueryExtensionsStringReply reply; 2223 __GLXscreen *pGlxScreen; 2224 size_t n, length; 2225 char *buf; 2226 int err; 2227 2228 REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq); 2229 2230 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2231 return err; 2232 2233 n = strlen(pGlxScreen->GLXextensions) + 1; 2234 length = __GLX_PAD(n) >> 2; 2235 reply.type = X_Reply; 2236 reply.sequenceNumber = client->sequence; 2237 reply.length = length; 2238 reply.n = n; 2239 2240 /* Allocate buffer to make sure it's a multiple of 4 bytes big.*/ 2241 buf = (char *) malloc(length << 2); 2242 if (buf == NULL) 2243 return BadAlloc; 2244 memcpy(buf, pGlxScreen->GLXextensions, n); 2245 2246 if (client->swapped) { 2247 glxSwapQueryExtensionsStringReply(client, &reply, buf); 2248 } else { 2249 WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply); 2250 WriteToClient(client, (int)(length << 2), (char *)buf); 2251 } 2252 2253 free(buf); 2254 return Success; 2255} 2256 2257int __glXDisp_QueryServerString(__GLXclientState *cl, GLbyte *pc) 2258{ 2259 ClientPtr client = cl->client; 2260 xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; 2261 xGLXQueryServerStringReply reply; 2262 size_t n, length; 2263 const char *ptr; 2264 char *buf; 2265 __GLXscreen *pGlxScreen; 2266 int err; 2267 char ver_str[16]; 2268 2269 REQUEST_SIZE_MATCH(xGLXQueryServerStringReq); 2270 2271 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2272 return err; 2273 2274 switch(req->name) { 2275 case GLX_VENDOR: 2276 ptr = pGlxScreen->GLXvendor; 2277 break; 2278 case GLX_VERSION: 2279 /* Return to the server version rather than the screen version 2280 * to prevent confusion when they do not match. 2281 */ 2282 snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion); 2283 ptr = ver_str; 2284 break; 2285 case GLX_EXTENSIONS: 2286 ptr = pGlxScreen->GLXextensions; 2287 break; 2288 default: 2289 return BadValue; 2290 } 2291 2292 n = strlen(ptr) + 1; 2293 length = __GLX_PAD(n) >> 2; 2294 reply.type = X_Reply; 2295 reply.sequenceNumber = client->sequence; 2296 reply.length = length; 2297 reply.n = n; 2298 2299 buf = (char *) malloc(length << 2); 2300 if (buf == NULL) { 2301 return BadAlloc; 2302 } 2303 memcpy(buf, ptr, n); 2304 2305 if (client->swapped) { 2306 glxSwapQueryServerStringReply(client, &reply, buf); 2307 } else { 2308 WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply); 2309 WriteToClient(client, (int)(length << 2), buf); 2310 } 2311 2312 free(buf); 2313 return Success; 2314} 2315 2316int __glXDisp_ClientInfo(__GLXclientState *cl, GLbyte *pc) 2317{ 2318 ClientPtr client = cl->client; 2319 xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; 2320 const char *buf; 2321 2322 REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq); 2323 2324 buf = (const char *)(req+1); 2325 if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq))) 2326 return BadLength; 2327 2328 cl->GLClientmajorVersion = req->major; 2329 cl->GLClientminorVersion = req->minor; 2330 free(cl->GLClientextensions); 2331 cl->GLClientextensions = strdup(buf); 2332 2333 return Success; 2334} 2335