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