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