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