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