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