glxcmds.c revision a259eee8
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->config = config; 1141 drawable->eventMask = 0; 1142 1143 return GL_TRUE; 1144} 1145 1146void 1147__glXDrawableRelease(__GLXdrawable * drawable) 1148{ 1149} 1150 1151static int 1152DoCreateGLXDrawable(ClientPtr client, __GLXscreen * pGlxScreen, 1153 __GLXconfig * config, DrawablePtr pDraw, XID drawableId, 1154 XID glxDrawableId, int type) 1155{ 1156 __GLXdrawable *pGlxDraw; 1157 1158 if (pGlxScreen->pScreen != pDraw->pScreen) 1159 return BadMatch; 1160 1161 pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw, 1162 drawableId, type, 1163 glxDrawableId, config); 1164 if (pGlxDraw == NULL) 1165 return BadAlloc; 1166 1167 if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw)) 1168 return BadAlloc; 1169 1170 /* 1171 * Windows aren't refcounted, so track both the X and the GLX window 1172 * so we get called regardless of destruction order. 1173 */ 1174 if (drawableId != glxDrawableId && type == GLX_DRAWABLE_WINDOW && 1175 !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) 1176 return BadAlloc; 1177 1178 return Success; 1179} 1180 1181static int 1182DoCreateGLXPixmap(ClientPtr client, __GLXscreen * pGlxScreen, 1183 __GLXconfig * config, XID drawableId, XID glxDrawableId) 1184{ 1185 DrawablePtr pDraw; 1186 int err; 1187 1188 err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess); 1189 if (err != Success) { 1190 client->errorValue = drawableId; 1191 return err; 1192 } 1193 if (pDraw->type != DRAWABLE_PIXMAP) { 1194 client->errorValue = drawableId; 1195 return BadPixmap; 1196 } 1197 1198 err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, 1199 glxDrawableId, GLX_DRAWABLE_PIXMAP); 1200 1201 if (err == Success) 1202 ((PixmapPtr) pDraw)->refcnt++; 1203 1204 return err; 1205} 1206 1207static void 1208determineTextureTarget(ClientPtr client, XID glxDrawableID, 1209 CARD32 *attribs, CARD32 numAttribs) 1210{ 1211 GLenum target = 0; 1212 GLenum format = 0; 1213 int i, err; 1214 __GLXdrawable *pGlxDraw; 1215 1216 if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP, 1217 DixWriteAccess, &pGlxDraw, &err)) 1218 /* We just added it in CreatePixmap, so we should never get here. */ 1219 return; 1220 1221 for (i = 0; i < numAttribs; i++) { 1222 if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { 1223 switch (attribs[2 * i + 1]) { 1224 case GLX_TEXTURE_2D_EXT: 1225 target = GL_TEXTURE_2D; 1226 break; 1227 case GLX_TEXTURE_RECTANGLE_EXT: 1228 target = GL_TEXTURE_RECTANGLE_ARB; 1229 break; 1230 } 1231 } 1232 1233 if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT) 1234 format = attribs[2 * i + 1]; 1235 } 1236 1237 if (!target) { 1238 int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height; 1239 1240 if (h & (h - 1) || w & (w - 1)) 1241 target = GL_TEXTURE_RECTANGLE_ARB; 1242 else 1243 target = GL_TEXTURE_2D; 1244 } 1245 1246 pGlxDraw->target = target; 1247 pGlxDraw->format = format; 1248} 1249 1250int 1251__glXDisp_CreateGLXPixmap(__GLXclientState * cl, GLbyte * pc) 1252{ 1253 xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; 1254 __GLXconfig *config; 1255 __GLXscreen *pGlxScreen; 1256 int err; 1257 1258 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1259 return err; 1260 if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err)) 1261 return err; 1262 1263 return DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1264 req->pixmap, req->glxpixmap); 1265} 1266 1267int 1268__glXDisp_CreatePixmap(__GLXclientState * cl, GLbyte * pc) 1269{ 1270 ClientPtr client = cl->client; 1271 xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; 1272 __GLXconfig *config; 1273 __GLXscreen *pGlxScreen; 1274 int err; 1275 1276 REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq); 1277 if (req->numAttribs > (UINT32_MAX >> 3)) { 1278 client->errorValue = req->numAttribs; 1279 return BadValue; 1280 } 1281 REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3); 1282 1283 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1284 return err; 1285 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1286 return err; 1287 1288 err = DoCreateGLXPixmap(cl->client, pGlxScreen, config, 1289 req->pixmap, req->glxpixmap); 1290 if (err != Success) 1291 return err; 1292 1293 determineTextureTarget(cl->client, req->glxpixmap, 1294 (CARD32 *) (req + 1), req->numAttribs); 1295 1296 return Success; 1297} 1298 1299int 1300__glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState * cl, GLbyte * pc) 1301{ 1302 ClientPtr client = cl->client; 1303 xGLXCreateGLXPixmapWithConfigSGIXReq *req = 1304 (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; 1305 __GLXconfig *config; 1306 __GLXscreen *pGlxScreen; 1307 int err; 1308 1309 REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq); 1310 1311 if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err)) 1312 return err; 1313 if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err)) 1314 return err; 1315 1316 return DoCreateGLXPixmap(cl->client, pGlxScreen, 1317 config, req->pixmap, req->glxpixmap); 1318} 1319 1320static int 1321DoDestroyDrawable(__GLXclientState * cl, XID glxdrawable, int type) 1322{ 1323 __GLXdrawable *pGlxDraw; 1324 int err; 1325 1326 if (!validGlxDrawable(cl->client, glxdrawable, type, 1327 DixDestroyAccess, &pGlxDraw, &err)) 1328 return err; 1329 1330 FreeResource(glxdrawable, FALSE); 1331 1332 return Success; 1333} 1334 1335int 1336__glXDisp_DestroyGLXPixmap(__GLXclientState * cl, GLbyte * pc) 1337{ 1338 xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; 1339 1340 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1341} 1342 1343int 1344__glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc) 1345{ 1346 ClientPtr client = cl->client; 1347 xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; 1348 1349 /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set 1350 * length to 3 instead of 2 */ 1351 REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq); 1352 1353 return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); 1354} 1355 1356static int 1357DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, 1358 int width, int height, XID glxDrawableId) 1359{ 1360 __GLXconfig *config; 1361 __GLXscreen *pGlxScreen; 1362 PixmapPtr pPixmap; 1363 int err; 1364 1365 if (!validGlxScreen(client, screenNum, &pGlxScreen, &err)) 1366 return err; 1367 if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err)) 1368 return err; 1369 1370 pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen, 1371 width, height, 1372 config->rgbBits, 0); 1373 if (!pPixmap) 1374 return BadAlloc; 1375 1376 /* Assign the pixmap the same id as the pbuffer and add it as a 1377 * resource so it and the DRI2 drawable will be reclaimed when the 1378 * pbuffer is destroyed. */ 1379 pPixmap->drawable.id = glxDrawableId; 1380 if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap)) 1381 return BadAlloc; 1382 1383 return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, 1384 glxDrawableId, glxDrawableId, 1385 GLX_DRAWABLE_PBUFFER); 1386} 1387 1388int 1389__glXDisp_CreatePbuffer(__GLXclientState * cl, GLbyte * pc) 1390{ 1391 ClientPtr client = cl->client; 1392 xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc; 1393 CARD32 *attrs; 1394 int width, height, i; 1395 1396 REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq); 1397 if (req->numAttribs > (UINT32_MAX >> 3)) { 1398 client->errorValue = req->numAttribs; 1399 return BadValue; 1400 } 1401 REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3); 1402 1403 attrs = (CARD32 *) (req + 1); 1404 width = 0; 1405 height = 0; 1406 1407 for (i = 0; i < req->numAttribs; i++) { 1408 switch (attrs[i * 2]) { 1409 case GLX_PBUFFER_WIDTH: 1410 width = attrs[i * 2 + 1]; 1411 break; 1412 case GLX_PBUFFER_HEIGHT: 1413 height = attrs[i * 2 + 1]; 1414 break; 1415 case GLX_LARGEST_PBUFFER: 1416 /* FIXME: huh... */ 1417 break; 1418 } 1419 } 1420 1421 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1422 width, height, req->pbuffer); 1423} 1424 1425int 1426__glXDisp_CreateGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc) 1427{ 1428 ClientPtr client = cl->client; 1429 xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc; 1430 1431 REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq); 1432 1433 /* 1434 * We should really handle attributes correctly, but this extension 1435 * is so rare I have difficulty caring. 1436 */ 1437 return DoCreatePbuffer(cl->client, req->screen, req->fbconfig, 1438 req->width, req->height, req->pbuffer); 1439} 1440 1441int 1442__glXDisp_DestroyPbuffer(__GLXclientState * cl, GLbyte * pc) 1443{ 1444 ClientPtr client = cl->client; 1445 xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc; 1446 1447 REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq); 1448 1449 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1450} 1451 1452int 1453__glXDisp_DestroyGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc) 1454{ 1455 ClientPtr client = cl->client; 1456 xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc; 1457 1458 REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq); 1459 1460 return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER); 1461} 1462 1463static int 1464DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable, 1465 int numAttribs, CARD32 *attribs) 1466{ 1467 __GLXdrawable *pGlxDraw; 1468 int i, err; 1469 1470 if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY, 1471 DixSetAttrAccess, &pGlxDraw, &err)) 1472 return err; 1473 1474 for (i = 0; i < numAttribs; i++) { 1475 switch (attribs[i * 2]) { 1476 case GLX_EVENT_MASK: 1477 /* All we do is to record the event mask so we can send it 1478 * back when queried. We never actually clobber the 1479 * pbuffers, so we never need to send out the event. */ 1480 pGlxDraw->eventMask = attribs[i * 2 + 1]; 1481 break; 1482 } 1483 } 1484 1485 return Success; 1486} 1487 1488int 1489__glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc) 1490{ 1491 ClientPtr client = cl->client; 1492 xGLXChangeDrawableAttributesReq *req = 1493 (xGLXChangeDrawableAttributesReq *) pc; 1494 1495 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq); 1496 if (req->numAttribs > (UINT32_MAX >> 3)) { 1497 client->errorValue = req->numAttribs; 1498 return BadValue; 1499 } 1500#if 0 1501 /* mesa sends an additional 8 bytes */ 1502 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); 1503#else 1504 if (((sizeof(xGLXChangeDrawableAttributesReq) + 1505 (req->numAttribs << 3)) >> 2) < client->req_len) 1506 return BadLength; 1507#endif 1508 1509 return DoChangeDrawableAttributes(cl->client, req->drawable, 1510 req->numAttribs, (CARD32 *) (req + 1)); 1511} 1512 1513int 1514__glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc) 1515{ 1516 ClientPtr client = cl->client; 1517 xGLXChangeDrawableAttributesSGIXReq *req = 1518 (xGLXChangeDrawableAttributesSGIXReq *) pc; 1519 1520 REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq); 1521 if (req->numAttribs > (UINT32_MAX >> 3)) { 1522 client->errorValue = req->numAttribs; 1523 return BadValue; 1524 } 1525 REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq, 1526 req->numAttribs << 3); 1527 1528 return DoChangeDrawableAttributes(cl->client, req->drawable, 1529 req->numAttribs, (CARD32 *) (req + 1)); 1530} 1531 1532int 1533__glXDisp_CreateWindow(__GLXclientState * cl, GLbyte * pc) 1534{ 1535 xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc; 1536 __GLXconfig *config; 1537 __GLXscreen *pGlxScreen; 1538 ClientPtr client = cl->client; 1539 DrawablePtr pDraw; 1540 int err; 1541 1542 REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq); 1543 if (req->numAttribs > (UINT32_MAX >> 3)) { 1544 client->errorValue = req->numAttribs; 1545 return BadValue; 1546 } 1547 REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3); 1548 1549 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 1550 return err; 1551 if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err)) 1552 return err; 1553 1554 err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess); 1555 if (err != Success || pDraw->type != DRAWABLE_WINDOW) { 1556 client->errorValue = req->window; 1557 return BadWindow; 1558 } 1559 1560 if (!validGlxFBConfigForWindow(client, config, pDraw, &err)) 1561 return err; 1562 1563 return DoCreateGLXDrawable(client, pGlxScreen, config, 1564 pDraw, req->window, 1565 req->glxwindow, GLX_DRAWABLE_WINDOW); 1566} 1567 1568int 1569__glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc) 1570{ 1571 ClientPtr client = cl->client; 1572 xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; 1573 1574 /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */ 1575 REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq); 1576 1577 return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); 1578} 1579 1580/*****************************************************************************/ 1581 1582/* 1583** NOTE: There is no portable implementation for swap buffers as of 1584** this time that is of value. Consequently, this code must be 1585** implemented by somebody other than SGI. 1586*/ 1587int 1588__glXDisp_SwapBuffers(__GLXclientState * cl, GLbyte * pc) 1589{ 1590 ClientPtr client = cl->client; 1591 xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; 1592 GLXContextTag tag; 1593 XID drawId; 1594 __GLXcontext *glxc = NULL; 1595 __GLXdrawable *pGlxDraw; 1596 int error; 1597 1598 tag = req->contextTag; 1599 drawId = req->drawable; 1600 if (tag) { 1601 glxc = __glXLookupContextByTag(cl, tag); 1602 if (!glxc) { 1603 return __glXError(GLXBadContextTag); 1604 } 1605 /* 1606 ** The calling thread is swapping its current drawable. In this case, 1607 ** glxSwapBuffers is in both GL and X streams, in terms of 1608 ** sequentiality. 1609 */ 1610 if (__glXForceCurrent(cl, tag, &error)) { 1611 /* 1612 ** Do whatever is needed to make sure that all preceding requests 1613 ** in both streams are completed before the swap is executed. 1614 */ 1615 glFinish(); 1616 } 1617 else { 1618 return error; 1619 } 1620 } 1621 1622 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1623 if (pGlxDraw == NULL) 1624 return error; 1625 1626 if (pGlxDraw->type == DRAWABLE_WINDOW && 1627 (*pGlxDraw->swapBuffers) (cl->client, pGlxDraw) == GL_FALSE) 1628 return __glXError(GLXBadDrawable); 1629 1630 return Success; 1631} 1632 1633static int 1634DoQueryContext(__GLXclientState * cl, GLXContextID gcId) 1635{ 1636 ClientPtr client = cl->client; 1637 __GLXcontext *ctx; 1638 xGLXQueryContextInfoEXTReply reply; 1639 int nProps = 5; 1640 int sendBuf[nProps * 2]; 1641 int nReplyBytes; 1642 int err; 1643 1644 if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err)) 1645 return err; 1646 1647 reply = (xGLXQueryContextInfoEXTReply) { 1648 .type = X_Reply, 1649 .sequenceNumber = client->sequence, 1650 .length = nProps << 1, 1651 .n = nProps 1652 }; 1653 1654 nReplyBytes = reply.length << 2; 1655 sendBuf[0] = GLX_SHARE_CONTEXT_EXT; 1656 sendBuf[1] = (int) (ctx->share_id); 1657 sendBuf[2] = GLX_VISUAL_ID_EXT; 1658 sendBuf[3] = (int) (ctx->config ? ctx->config->visualID : 0); 1659 sendBuf[4] = GLX_SCREEN_EXT; 1660 sendBuf[5] = (int) (ctx->pGlxScreen->pScreen->myNum); 1661 sendBuf[6] = GLX_FBCONFIG_ID; 1662 sendBuf[7] = (int) (ctx->config ? ctx->config->fbconfigID : 0); 1663 sendBuf[8] = GLX_RENDER_TYPE; 1664 sendBuf[9] = (int) (ctx->config ? ctx->config->renderType : GLX_DONT_CARE); 1665 1666 if (client->swapped) { 1667 int length = reply.length; 1668 1669 __GLX_DECLARE_SWAP_VARIABLES; 1670 __GLX_DECLARE_SWAP_ARRAY_VARIABLES; 1671 __GLX_SWAP_SHORT(&reply.sequenceNumber); 1672 __GLX_SWAP_INT(&reply.length); 1673 __GLX_SWAP_INT(&reply.n); 1674 WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, &reply); 1675 __GLX_SWAP_INT_ARRAY((int *) sendBuf, length); 1676 WriteToClient(client, length << 2, sendBuf); 1677 } 1678 else { 1679 WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, &reply); 1680 WriteToClient(client, nReplyBytes, sendBuf); 1681 } 1682 1683 return Success; 1684} 1685 1686int 1687__glXDisp_QueryContextInfoEXT(__GLXclientState * cl, GLbyte * pc) 1688{ 1689 ClientPtr client = cl->client; 1690 xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc; 1691 1692 REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq); 1693 1694 return DoQueryContext(cl, req->context); 1695} 1696 1697int 1698__glXDisp_QueryContext(__GLXclientState * cl, GLbyte * pc) 1699{ 1700 xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc; 1701 1702 return DoQueryContext(cl, req->context); 1703} 1704 1705int 1706__glXDisp_BindTexImageEXT(__GLXclientState * cl, GLbyte * pc) 1707{ 1708 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1709 ClientPtr client = cl->client; 1710 __GLXcontext *context; 1711 __GLXdrawable *pGlxDraw; 1712 GLXDrawable drawId; 1713 int buffer; 1714 int error; 1715 CARD32 num_attribs; 1716 1717 if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len) 1718 return BadLength; 1719 1720 pc += __GLX_VENDPRIV_HDR_SIZE; 1721 1722 drawId = *((CARD32 *) (pc)); 1723 buffer = *((INT32 *) (pc + 4)); 1724 num_attribs = *((CARD32 *) (pc + 8)); 1725 if (num_attribs > (UINT32_MAX >> 3)) { 1726 client->errorValue = num_attribs; 1727 return BadValue; 1728 } 1729 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3)); 1730 1731 if (buffer != GLX_FRONT_LEFT_EXT) 1732 return __glXError(GLXBadPixmap); 1733 1734 context = __glXForceCurrent(cl, req->contextTag, &error); 1735 if (!context) 1736 return error; 1737 1738 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1739 DixReadAccess, &pGlxDraw, &error)) 1740 return error; 1741 1742 if (!context->bindTexImage) 1743 return __glXError(GLXUnsupportedPrivateRequest); 1744 1745 return context->bindTexImage(context, buffer, pGlxDraw); 1746} 1747 1748int 1749__glXDisp_ReleaseTexImageEXT(__GLXclientState * cl, GLbyte * pc) 1750{ 1751 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1752 ClientPtr client = cl->client; 1753 __GLXdrawable *pGlxDraw; 1754 __GLXcontext *context; 1755 GLXDrawable drawId; 1756 int buffer; 1757 int error; 1758 1759 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8); 1760 1761 pc += __GLX_VENDPRIV_HDR_SIZE; 1762 1763 drawId = *((CARD32 *) (pc)); 1764 buffer = *((INT32 *) (pc + 4)); 1765 1766 context = __glXForceCurrent(cl, req->contextTag, &error); 1767 if (!context) 1768 return error; 1769 1770 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP, 1771 DixReadAccess, &pGlxDraw, &error)) 1772 return error; 1773 1774 if (!context->releaseTexImage) 1775 return __glXError(GLXUnsupportedPrivateRequest); 1776 1777 return context->releaseTexImage(context, buffer, pGlxDraw); 1778} 1779 1780int 1781__glXDisp_CopySubBufferMESA(__GLXclientState * cl, GLbyte * pc) 1782{ 1783 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 1784 GLXContextTag tag = req->contextTag; 1785 __GLXcontext *glxc = NULL; 1786 __GLXdrawable *pGlxDraw; 1787 ClientPtr client = cl->client; 1788 GLXDrawable drawId; 1789 int error; 1790 int x, y, width, height; 1791 1792 (void) client; 1793 (void) req; 1794 1795 REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20); 1796 1797 pc += __GLX_VENDPRIV_HDR_SIZE; 1798 1799 drawId = *((CARD32 *) (pc)); 1800 x = *((INT32 *) (pc + 4)); 1801 y = *((INT32 *) (pc + 8)); 1802 width = *((INT32 *) (pc + 12)); 1803 height = *((INT32 *) (pc + 16)); 1804 1805 if (tag) { 1806 glxc = __glXLookupContextByTag(cl, tag); 1807 if (!glxc) { 1808 return __glXError(GLXBadContextTag); 1809 } 1810 /* 1811 ** The calling thread is swapping its current drawable. In this case, 1812 ** glxSwapBuffers is in both GL and X streams, in terms of 1813 ** sequentiality. 1814 */ 1815 if (__glXForceCurrent(cl, tag, &error)) { 1816 /* 1817 ** Do whatever is needed to make sure that all preceding requests 1818 ** in both streams are completed before the swap is executed. 1819 */ 1820 glFinish(); 1821 } 1822 else { 1823 return error; 1824 } 1825 } 1826 1827 pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error); 1828 if (!pGlxDraw) 1829 return error; 1830 1831 if (pGlxDraw == NULL || 1832 pGlxDraw->type != GLX_DRAWABLE_WINDOW || 1833 pGlxDraw->copySubBuffer == NULL) 1834 return __glXError(GLXBadDrawable); 1835 1836 (*pGlxDraw->copySubBuffer) (pGlxDraw, x, y, width, height); 1837 1838 return Success; 1839} 1840 1841/* hack for old glxext.h */ 1842#ifndef GLX_STEREO_TREE_EXT 1843#define GLX_STEREO_TREE_EXT 0x20F5 1844#endif 1845 1846/* 1847** Get drawable attributes 1848*/ 1849static int 1850DoGetDrawableAttributes(__GLXclientState * cl, XID drawId) 1851{ 1852 ClientPtr client = cl->client; 1853 xGLXGetDrawableAttributesReply reply; 1854 __GLXdrawable *pGlxDraw = NULL; 1855 DrawablePtr pDraw; 1856 CARD32 attributes[18]; 1857 int num = 0, error; 1858 1859 if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, 1860 DixGetAttrAccess, &pGlxDraw, &error)) { 1861 /* hack for GLX 1.2 naked windows */ 1862 int err = dixLookupWindow((WindowPtr *)&pDraw, drawId, client, 1863 DixGetAttrAccess); 1864 if (err != Success) 1865 return error; 1866 } 1867 if (pGlxDraw) 1868 pDraw = pGlxDraw->pDraw; 1869 1870#define ATTRIB(a, v) do { \ 1871 attributes[2*num] = (a); \ 1872 attributes[2*num+1] = (v); \ 1873 num++; \ 1874 } while (0) 1875 1876 ATTRIB(GLX_Y_INVERTED_EXT, GL_FALSE); 1877 ATTRIB(GLX_WIDTH, pDraw->width); 1878 ATTRIB(GLX_HEIGHT, pDraw->height); 1879 ATTRIB(GLX_SCREEN, pDraw->pScreen->myNum); 1880 if (pGlxDraw) { 1881 ATTRIB(GLX_TEXTURE_TARGET_EXT, 1882 pGlxDraw->target == GL_TEXTURE_2D ? 1883 GLX_TEXTURE_2D_EXT : GLX_TEXTURE_RECTANGLE_EXT); 1884 ATTRIB(GLX_EVENT_MASK, pGlxDraw->eventMask); 1885 ATTRIB(GLX_FBCONFIG_ID, pGlxDraw->config->fbconfigID); 1886 if (pGlxDraw->type == GLX_DRAWABLE_PBUFFER) { 1887 ATTRIB(GLX_PRESERVED_CONTENTS, GL_TRUE); 1888 } 1889 if (pGlxDraw->type == GLX_DRAWABLE_WINDOW) { 1890 ATTRIB(GLX_STEREO_TREE_EXT, 0); 1891 } 1892 } 1893#undef ATTRIB 1894 1895 reply = (xGLXGetDrawableAttributesReply) { 1896 .type = X_Reply, 1897 .sequenceNumber = client->sequence, 1898 .length = num << 1, 1899 .numAttribs = num 1900 }; 1901 1902 if (client->swapped) { 1903 int length = reply.length; 1904 1905 __GLX_DECLARE_SWAP_VARIABLES; 1906 __GLX_DECLARE_SWAP_ARRAY_VARIABLES; 1907 __GLX_SWAP_SHORT(&reply.sequenceNumber); 1908 __GLX_SWAP_INT(&reply.length); 1909 __GLX_SWAP_INT(&reply.numAttribs); 1910 WriteToClient(client, sz_xGLXGetDrawableAttributesReply, &reply); 1911 __GLX_SWAP_INT_ARRAY((int *) attributes, length); 1912 WriteToClient(client, length << 2, attributes); 1913 } 1914 else { 1915 WriteToClient(client, sz_xGLXGetDrawableAttributesReply, &reply); 1916 WriteToClient(client, reply.length * sizeof(CARD32), attributes); 1917 } 1918 1919 return Success; 1920} 1921 1922int 1923__glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc) 1924{ 1925 ClientPtr client = cl->client; 1926 xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc; 1927 1928 /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */ 1929 REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq); 1930 1931 return DoGetDrawableAttributes(cl, req->drawable); 1932} 1933 1934int 1935__glXDisp_GetDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc) 1936{ 1937 ClientPtr client = cl->client; 1938 xGLXGetDrawableAttributesSGIXReq *req = 1939 (xGLXGetDrawableAttributesSGIXReq *) pc; 1940 1941 REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq); 1942 1943 return DoGetDrawableAttributes(cl, req->drawable); 1944} 1945 1946/************************************************************************/ 1947 1948/* 1949** Render and Renderlarge are not in the GLX API. They are used by the GLX 1950** client library to send batches of GL rendering commands. 1951*/ 1952 1953/* 1954** Reset state used to keep track of large (multi-request) commands. 1955*/ 1956static void 1957ResetLargeCommandStatus(__GLXcontext *cx) 1958{ 1959 cx->largeCmdBytesSoFar = 0; 1960 cx->largeCmdBytesTotal = 0; 1961 cx->largeCmdRequestsSoFar = 0; 1962 cx->largeCmdRequestsTotal = 0; 1963} 1964 1965/* 1966** Execute all the drawing commands in a request. 1967*/ 1968int 1969__glXDisp_Render(__GLXclientState * cl, GLbyte * pc) 1970{ 1971 xGLXRenderReq *req; 1972 ClientPtr client = cl->client; 1973 int left, cmdlen, error; 1974 int commandsDone; 1975 CARD16 opcode; 1976 __GLXrenderHeader *hdr; 1977 __GLXcontext *glxc; 1978 1979 __GLX_DECLARE_SWAP_VARIABLES; 1980 1981 REQUEST_AT_LEAST_SIZE(xGLXRenderReq); 1982 1983 req = (xGLXRenderReq *) pc; 1984 if (client->swapped) { 1985 __GLX_SWAP_SHORT(&req->length); 1986 __GLX_SWAP_INT(&req->contextTag); 1987 } 1988 1989 glxc = __glXForceCurrent(cl, req->contextTag, &error); 1990 if (!glxc) { 1991 return error; 1992 } 1993 1994 commandsDone = 0; 1995 pc += sz_xGLXRenderReq; 1996 left = (req->length << 2) - sz_xGLXRenderReq; 1997 while (left > 0) { 1998 __GLXrenderSizeData entry; 1999 int extra = 0; 2000 __GLXdispatchRenderProcPtr proc; 2001 int err; 2002 2003 if (left < sizeof(__GLXrenderHeader)) 2004 return BadLength; 2005 2006 /* 2007 ** Verify that the header length and the overall length agree. 2008 ** Also, each command must be word aligned. 2009 */ 2010 hdr = (__GLXrenderHeader *) pc; 2011 if (client->swapped) { 2012 __GLX_SWAP_SHORT(&hdr->length); 2013 __GLX_SWAP_SHORT(&hdr->opcode); 2014 } 2015 cmdlen = hdr->length; 2016 opcode = hdr->opcode; 2017 2018 if (left < cmdlen) 2019 return BadLength; 2020 2021 /* 2022 ** Check for core opcodes and grab entry data. 2023 */ 2024 err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry); 2025 proc = (__GLXdispatchRenderProcPtr) 2026 __glXGetProtocolDecodeFunction(&Render_dispatch_info, 2027 opcode, client->swapped); 2028 2029 if ((err < 0) || (proc == NULL)) { 2030 client->errorValue = commandsDone; 2031 return __glXError(GLXBadRenderRequest); 2032 } 2033 2034 if (cmdlen < entry.bytes) { 2035 return BadLength; 2036 } 2037 2038 if (entry.varsize) { 2039 /* variable size command */ 2040 extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE, 2041 client->swapped, 2042 left - __GLX_RENDER_HDR_SIZE); 2043 if (extra < 0) { 2044 return BadLength; 2045 } 2046 } 2047 2048 if (cmdlen != safe_pad(safe_add(entry.bytes, extra))) { 2049 return BadLength; 2050 } 2051 2052 /* 2053 ** Skip over the header and execute the command. We allow the 2054 ** caller to trash the command memory. This is useful especially 2055 ** for things that require double alignment - they can just shift 2056 ** the data towards lower memory (trashing the header) by 4 bytes 2057 ** and achieve the required alignment. 2058 */ 2059 (*proc) (pc + __GLX_RENDER_HDR_SIZE); 2060 pc += cmdlen; 2061 left -= cmdlen; 2062 commandsDone++; 2063 } 2064 return Success; 2065} 2066 2067/* 2068** Execute a large rendering request (one that spans multiple X requests). 2069*/ 2070int 2071__glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc) 2072{ 2073 xGLXRenderLargeReq *req; 2074 ClientPtr client = cl->client; 2075 size_t dataBytes; 2076 __GLXrenderLargeHeader *hdr; 2077 __GLXcontext *glxc; 2078 int error; 2079 CARD16 opcode; 2080 2081 __GLX_DECLARE_SWAP_VARIABLES; 2082 2083 REQUEST_AT_LEAST_SIZE(xGLXRenderLargeReq); 2084 2085 req = (xGLXRenderLargeReq *) pc; 2086 if (client->swapped) { 2087 __GLX_SWAP_SHORT(&req->length); 2088 __GLX_SWAP_INT(&req->contextTag); 2089 __GLX_SWAP_INT(&req->dataBytes); 2090 __GLX_SWAP_SHORT(&req->requestNumber); 2091 __GLX_SWAP_SHORT(&req->requestTotal); 2092 } 2093 2094 glxc = __glXForceCurrent(cl, req->contextTag, &error); 2095 if (!glxc) { 2096 return error; 2097 } 2098 if (safe_pad(req->dataBytes) < 0) 2099 return BadLength; 2100 dataBytes = req->dataBytes; 2101 2102 /* 2103 ** Check the request length. 2104 */ 2105 if ((req->length << 2) != safe_pad(dataBytes) + sz_xGLXRenderLargeReq) { 2106 client->errorValue = req->length; 2107 /* Reset in case this isn't 1st request. */ 2108 ResetLargeCommandStatus(glxc); 2109 return BadLength; 2110 } 2111 pc += sz_xGLXRenderLargeReq; 2112 2113 if (glxc->largeCmdRequestsSoFar == 0) { 2114 __GLXrenderSizeData entry; 2115 int extra = 0; 2116 int left = (req->length << 2) - sz_xGLXRenderLargeReq; 2117 int cmdlen; 2118 int err; 2119 2120 /* 2121 ** This is the first request of a multi request command. 2122 ** Make enough space in the buffer, then copy the entire request. 2123 */ 2124 if (req->requestNumber != 1) { 2125 client->errorValue = req->requestNumber; 2126 return __glXError(GLXBadLargeRequest); 2127 } 2128 2129 if (dataBytes < __GLX_RENDER_LARGE_HDR_SIZE) 2130 return BadLength; 2131 2132 hdr = (__GLXrenderLargeHeader *) pc; 2133 if (client->swapped) { 2134 __GLX_SWAP_INT(&hdr->length); 2135 __GLX_SWAP_INT(&hdr->opcode); 2136 } 2137 opcode = hdr->opcode; 2138 if ((cmdlen = safe_pad(hdr->length)) < 0) 2139 return BadLength; 2140 2141 /* 2142 ** Check for core opcodes and grab entry data. 2143 */ 2144 err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry); 2145 if (err < 0) { 2146 client->errorValue = opcode; 2147 return __glXError(GLXBadLargeRequest); 2148 } 2149 2150 if (entry.varsize) { 2151 /* 2152 ** If it's a variable-size command (a command whose length must 2153 ** be computed from its parameters), all the parameters needed 2154 ** will be in the 1st request, so it's okay to do this. 2155 */ 2156 extra = (*entry.varsize) (pc + __GLX_RENDER_LARGE_HDR_SIZE, 2157 client->swapped, 2158 left - __GLX_RENDER_LARGE_HDR_SIZE); 2159 if (extra < 0) { 2160 return BadLength; 2161 } 2162 } 2163 2164 /* the +4 is safe because we know entry.bytes is small */ 2165 if (cmdlen != safe_pad(safe_add(entry.bytes + 4, extra))) { 2166 return BadLength; 2167 } 2168 2169 /* 2170 ** Make enough space in the buffer, then copy the entire request. 2171 */ 2172 if (glxc->largeCmdBufSize < cmdlen) { 2173 GLbyte *newbuf = glxc->largeCmdBuf; 2174 2175 if (!(newbuf = realloc(newbuf, cmdlen))) 2176 return BadAlloc; 2177 2178 glxc->largeCmdBuf = newbuf; 2179 glxc->largeCmdBufSize = cmdlen; 2180 } 2181 memcpy(glxc->largeCmdBuf, pc, dataBytes); 2182 2183 glxc->largeCmdBytesSoFar = dataBytes; 2184 glxc->largeCmdBytesTotal = cmdlen; 2185 glxc->largeCmdRequestsSoFar = 1; 2186 glxc->largeCmdRequestsTotal = req->requestTotal; 2187 return Success; 2188 2189 } 2190 else { 2191 /* 2192 ** We are receiving subsequent (i.e. not the first) requests of a 2193 ** multi request command. 2194 */ 2195 int bytesSoFar; /* including this packet */ 2196 2197 /* 2198 ** Check the request number and the total request count. 2199 */ 2200 if (req->requestNumber != glxc->largeCmdRequestsSoFar + 1) { 2201 client->errorValue = req->requestNumber; 2202 ResetLargeCommandStatus(glxc); 2203 return __glXError(GLXBadLargeRequest); 2204 } 2205 if (req->requestTotal != glxc->largeCmdRequestsTotal) { 2206 client->errorValue = req->requestTotal; 2207 ResetLargeCommandStatus(glxc); 2208 return __glXError(GLXBadLargeRequest); 2209 } 2210 2211 /* 2212 ** Check that we didn't get too much data. 2213 */ 2214 if ((bytesSoFar = safe_add(glxc->largeCmdBytesSoFar, dataBytes)) < 0) { 2215 client->errorValue = dataBytes; 2216 ResetLargeCommandStatus(glxc); 2217 return __glXError(GLXBadLargeRequest); 2218 } 2219 2220 if (bytesSoFar > glxc->largeCmdBytesTotal) { 2221 client->errorValue = dataBytes; 2222 ResetLargeCommandStatus(glxc); 2223 return __glXError(GLXBadLargeRequest); 2224 } 2225 2226 memcpy(glxc->largeCmdBuf + glxc->largeCmdBytesSoFar, pc, dataBytes); 2227 glxc->largeCmdBytesSoFar += dataBytes; 2228 glxc->largeCmdRequestsSoFar++; 2229 2230 if (req->requestNumber == glxc->largeCmdRequestsTotal) { 2231 __GLXdispatchRenderProcPtr proc; 2232 2233 /* 2234 ** This is the last request; it must have enough bytes to complete 2235 ** the command. 2236 */ 2237 /* NOTE: the pad macro below is needed because the client library 2238 ** pads the total byte count, but not the per-request byte counts. 2239 ** The Protocol Encoding says the total byte count should not be 2240 ** padded, so a proposal will be made to the ARB to relax the 2241 ** padding constraint on the total byte count, thus preserving 2242 ** backward compatibility. Meanwhile, the padding done below 2243 ** fixes a bug that did not allow large commands of odd sizes to 2244 ** be accepted by the server. 2245 */ 2246 if (safe_pad(glxc->largeCmdBytesSoFar) != glxc->largeCmdBytesTotal) { 2247 client->errorValue = dataBytes; 2248 ResetLargeCommandStatus(glxc); 2249 return __glXError(GLXBadLargeRequest); 2250 } 2251 hdr = (__GLXrenderLargeHeader *) glxc->largeCmdBuf; 2252 /* 2253 ** The opcode and length field in the header had already been 2254 ** swapped when the first request was received. 2255 ** 2256 ** Use the opcode to index into the procedure table. 2257 */ 2258 opcode = hdr->opcode; 2259 2260 proc = (__GLXdispatchRenderProcPtr) 2261 __glXGetProtocolDecodeFunction(&Render_dispatch_info, opcode, 2262 client->swapped); 2263 if (proc == NULL) { 2264 client->errorValue = opcode; 2265 return __glXError(GLXBadLargeRequest); 2266 } 2267 2268 /* 2269 ** Skip over the header and execute the command. 2270 */ 2271 (*proc) (glxc->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE); 2272 2273 /* 2274 ** Reset for the next RenderLarge series. 2275 */ 2276 ResetLargeCommandStatus(glxc); 2277 } 2278 else { 2279 /* 2280 ** This is neither the first nor the last request. 2281 */ 2282 } 2283 return Success; 2284 } 2285} 2286 2287/************************************************************************/ 2288 2289/* 2290** No support is provided for the vendor-private requests other than 2291** allocating the entry points in the dispatch table. 2292*/ 2293 2294int 2295__glXDisp_VendorPrivate(__GLXclientState * cl, GLbyte * pc) 2296{ 2297 ClientPtr client = cl->client; 2298 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2299 GLint vendorcode = req->vendorCode; 2300 __GLXdispatchVendorPrivProcPtr proc; 2301 2302 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2303 2304 proc = (__GLXdispatchVendorPrivProcPtr) 2305 __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, 2306 vendorcode, 0); 2307 if (proc != NULL) { 2308 return (*proc) (cl, (GLbyte *) req); 2309 } 2310 2311 cl->client->errorValue = req->vendorCode; 2312 return __glXError(GLXUnsupportedPrivateRequest); 2313} 2314 2315int 2316__glXDisp_VendorPrivateWithReply(__GLXclientState * cl, GLbyte * pc) 2317{ 2318 ClientPtr client = cl->client; 2319 xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; 2320 GLint vendorcode = req->vendorCode; 2321 __GLXdispatchVendorPrivProcPtr proc; 2322 2323 REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq); 2324 2325 proc = (__GLXdispatchVendorPrivProcPtr) 2326 __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, 2327 vendorcode, 0); 2328 if (proc != NULL) { 2329 return (*proc) (cl, (GLbyte *) req); 2330 } 2331 2332 cl->client->errorValue = vendorcode; 2333 return __glXError(GLXUnsupportedPrivateRequest); 2334} 2335 2336int 2337__glXDisp_QueryExtensionsString(__GLXclientState * cl, GLbyte * pc) 2338{ 2339 ClientPtr client = cl->client; 2340 xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; 2341 xGLXQueryExtensionsStringReply reply; 2342 __GLXscreen *pGlxScreen; 2343 size_t n, length; 2344 char *buf; 2345 int err; 2346 2347 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2348 return err; 2349 2350 n = strlen(pGlxScreen->GLXextensions) + 1; 2351 length = __GLX_PAD(n) >> 2; 2352 reply = (xGLXQueryExtensionsStringReply) { 2353 .type = X_Reply, 2354 .sequenceNumber = client->sequence, 2355 .length = length, 2356 .n = n 2357 }; 2358 2359 /* Allocate buffer to make sure it's a multiple of 4 bytes big. */ 2360 buf = calloc(length, 4); 2361 if (buf == NULL) 2362 return BadAlloc; 2363 memcpy(buf, pGlxScreen->GLXextensions, n); 2364 2365 if (client->swapped) { 2366 __GLX_DECLARE_SWAP_VARIABLES; 2367 __GLX_DECLARE_SWAP_ARRAY_VARIABLES; 2368 __GLX_SWAP_SHORT(&reply.sequenceNumber); 2369 __GLX_SWAP_INT(&reply.length); 2370 __GLX_SWAP_INT(&reply.n); 2371 WriteToClient(client, sz_xGLXQueryExtensionsStringReply, &reply); 2372 __GLX_SWAP_INT_ARRAY((int *) buf, length); 2373 WriteToClient(client, length << 2, buf); 2374 } 2375 else { 2376 WriteToClient(client, sz_xGLXQueryExtensionsStringReply, &reply); 2377 WriteToClient(client, (int) (length << 2), buf); 2378 } 2379 2380 free(buf); 2381 return Success; 2382} 2383 2384#ifndef GLX_VENDOR_NAMES_EXT 2385#define GLX_VENDOR_NAMES_EXT 0x20F6 2386#endif 2387 2388int 2389__glXDisp_QueryServerString(__GLXclientState * cl, GLbyte * pc) 2390{ 2391 ClientPtr client = cl->client; 2392 xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; 2393 xGLXQueryServerStringReply reply; 2394 size_t n, length; 2395 const char *ptr; 2396 char *buf; 2397 __GLXscreen *pGlxScreen; 2398 int err; 2399 2400 if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) 2401 return err; 2402 2403 switch (req->name) { 2404 case GLX_VENDOR: 2405 ptr = GLXServerVendorName; 2406 break; 2407 case GLX_VERSION: 2408 ptr = "1.4"; 2409 break; 2410 case GLX_EXTENSIONS: 2411 ptr = pGlxScreen->GLXextensions; 2412 break; 2413 case GLX_VENDOR_NAMES_EXT: 2414 if (pGlxScreen->glvnd) { 2415 ptr = pGlxScreen->glvnd; 2416 break; 2417 } 2418 /* else fall through */ 2419 default: 2420 return BadValue; 2421 } 2422 2423 n = strlen(ptr) + 1; 2424 length = __GLX_PAD(n) >> 2; 2425 reply = (xGLXQueryServerStringReply) { 2426 .type = X_Reply, 2427 .sequenceNumber = client->sequence, 2428 .length = length, 2429 .n = n 2430 }; 2431 2432 buf = calloc(length, 4); 2433 if (buf == NULL) { 2434 return BadAlloc; 2435 } 2436 memcpy(buf, ptr, n); 2437 2438 if (client->swapped) { 2439 __GLX_DECLARE_SWAP_VARIABLES; 2440 __GLX_SWAP_SHORT(&reply.sequenceNumber); 2441 __GLX_SWAP_INT(&reply.length); 2442 __GLX_SWAP_INT(&reply.n); 2443 WriteToClient(client, sz_xGLXQueryServerStringReply, &reply); 2444 /** no swap is needed for an array of chars **/ 2445 /* __GLX_SWAP_INT_ARRAY((int *)buf, length); */ 2446 WriteToClient(client, length << 2, buf); 2447 } 2448 else { 2449 WriteToClient(client, sz_xGLXQueryServerStringReply, &reply); 2450 WriteToClient(client, (int) (length << 2), buf); 2451 } 2452 2453 free(buf); 2454 return Success; 2455} 2456 2457int 2458__glXDisp_ClientInfo(__GLXclientState * cl, GLbyte * pc) 2459{ 2460 ClientPtr client = cl->client; 2461 xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; 2462 const char *buf; 2463 2464 REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq); 2465 2466 buf = (const char *) (req + 1); 2467 if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq))) 2468 return BadLength; 2469 2470 free(cl->GLClientextensions); 2471 cl->GLClientextensions = strdup(buf); 2472 2473 return Success; 2474} 2475 2476#include <GL/glxtokens.h> 2477 2478void 2479__glXsendSwapEvent(__GLXdrawable *drawable, int type, CARD64 ust, 2480 CARD64 msc, CARD32 sbc) 2481{ 2482 ClientPtr client = clients[CLIENT_ID(drawable->drawId)]; 2483 2484 xGLXBufferSwapComplete2 wire = { 2485 .type = __glXEventBase + GLX_BufferSwapComplete 2486 }; 2487 2488 if (!client) 2489 return; 2490 2491 if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) 2492 return; 2493 2494 wire.event_type = type; 2495 wire.drawable = drawable->drawId; 2496 wire.ust_hi = ust >> 32; 2497 wire.ust_lo = ust & 0xffffffff; 2498 wire.msc_hi = msc >> 32; 2499 wire.msc_lo = msc & 0xffffffff; 2500 wire.sbc = sbc; 2501 2502 WriteEventsToClient(client, 1, (xEvent *) &wire); 2503} 2504 2505#if PRESENT 2506static void 2507__glXpresentCompleteNotify(WindowPtr window, CARD8 present_kind, CARD8 present_mode, 2508 CARD32 serial, uint64_t ust, uint64_t msc) 2509{ 2510 __GLXdrawable *drawable; 2511 int glx_type; 2512 int rc; 2513 2514 if (present_kind != PresentCompleteKindPixmap) 2515 return; 2516 2517 rc = dixLookupResourceByType((void **) &drawable, window->drawable.id, 2518 __glXDrawableRes, serverClient, DixGetAttrAccess); 2519 2520 if (rc != Success) 2521 return; 2522 2523 if (present_mode == PresentCompleteModeFlip) 2524 glx_type = GLX_FLIP_COMPLETE_INTEL; 2525 else 2526 glx_type = GLX_BLIT_COMPLETE_INTEL; 2527 2528 __glXsendSwapEvent(drawable, glx_type, ust, msc, serial); 2529} 2530 2531#include <present.h> 2532 2533void 2534__glXregisterPresentCompleteNotify(void) 2535{ 2536 present_register_complete_notify(__glXpresentCompleteNotify); 2537} 2538#endif 2539