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