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