xref: /OK3568_Linux_fs/external/xserver/glx/single2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3*4882a593Smuzhiyun  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
6*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
7*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
8*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
10*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * The above copyright notice including the dates of first publication and
13*4882a593Smuzhiyun  * either this permission notice or a reference to
14*4882a593Smuzhiyun  * http://oss.sgi.com/projects/FreeB/
15*4882a593Smuzhiyun  * shall be included in all copies or substantial portions of the Software.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*4882a593Smuzhiyun  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*4882a593Smuzhiyun  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21*4882a593Smuzhiyun  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22*4882a593Smuzhiyun  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*4882a593Smuzhiyun  * SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26*4882a593Smuzhiyun  * shall not be used in advertising or otherwise to promote the sale, use or
27*4882a593Smuzhiyun  * other dealings in this Software without prior written authorization from
28*4882a593Smuzhiyun  * Silicon Graphics, Inc.
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
32*4882a593Smuzhiyun #include <dix-config.h>
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <string.h>
36*4882a593Smuzhiyun #include <stdio.h>
37*4882a593Smuzhiyun #include <stdlib.h>
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include "glxserver.h"
40*4882a593Smuzhiyun #include "glxutil.h"
41*4882a593Smuzhiyun #include "glxext.h"
42*4882a593Smuzhiyun #include "indirect_dispatch.h"
43*4882a593Smuzhiyun #include "unpack.h"
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun int
__glXDisp_FeedbackBuffer(__GLXclientState * cl,GLbyte * pc)46*4882a593Smuzhiyun __glXDisp_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun     ClientPtr client = cl->client;
49*4882a593Smuzhiyun     GLsizei size;
50*4882a593Smuzhiyun     GLenum type;
51*4882a593Smuzhiyun     __GLXcontext *cx;
52*4882a593Smuzhiyun     int error;
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xGLXSingleReq, 8);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
57*4882a593Smuzhiyun     if (!cx) {
58*4882a593Smuzhiyun         return error;
59*4882a593Smuzhiyun     }
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun     pc += __GLX_SINGLE_HDR_SIZE;
62*4882a593Smuzhiyun     size = *(GLsizei *) (pc + 0);
63*4882a593Smuzhiyun     type = *(GLenum *) (pc + 4);
64*4882a593Smuzhiyun     if (cx->feedbackBufSize < size) {
65*4882a593Smuzhiyun         cx->feedbackBuf = reallocarray(cx->feedbackBuf,
66*4882a593Smuzhiyun                                        (size_t) size, __GLX_SIZE_FLOAT32);
67*4882a593Smuzhiyun         if (!cx->feedbackBuf) {
68*4882a593Smuzhiyun             cl->client->errorValue = size;
69*4882a593Smuzhiyun             return BadAlloc;
70*4882a593Smuzhiyun         }
71*4882a593Smuzhiyun         cx->feedbackBufSize = size;
72*4882a593Smuzhiyun     }
73*4882a593Smuzhiyun     glFeedbackBuffer(size, type, cx->feedbackBuf);
74*4882a593Smuzhiyun     return Success;
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun int
__glXDisp_SelectBuffer(__GLXclientState * cl,GLbyte * pc)78*4882a593Smuzhiyun __glXDisp_SelectBuffer(__GLXclientState * cl, GLbyte * pc)
79*4882a593Smuzhiyun {
80*4882a593Smuzhiyun     ClientPtr client = cl->client;
81*4882a593Smuzhiyun     __GLXcontext *cx;
82*4882a593Smuzhiyun     GLsizei size;
83*4882a593Smuzhiyun     int error;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
88*4882a593Smuzhiyun     if (!cx) {
89*4882a593Smuzhiyun         return error;
90*4882a593Smuzhiyun     }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun     pc += __GLX_SINGLE_HDR_SIZE;
93*4882a593Smuzhiyun     size = *(GLsizei *) (pc + 0);
94*4882a593Smuzhiyun     if (cx->selectBufSize < size) {
95*4882a593Smuzhiyun         cx->selectBuf = reallocarray(cx->selectBuf,
96*4882a593Smuzhiyun                                      (size_t) size, __GLX_SIZE_CARD32);
97*4882a593Smuzhiyun         if (!cx->selectBuf) {
98*4882a593Smuzhiyun             cl->client->errorValue = size;
99*4882a593Smuzhiyun             return BadAlloc;
100*4882a593Smuzhiyun         }
101*4882a593Smuzhiyun         cx->selectBufSize = size;
102*4882a593Smuzhiyun     }
103*4882a593Smuzhiyun     glSelectBuffer(size, cx->selectBuf);
104*4882a593Smuzhiyun     return Success;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun int
__glXDisp_RenderMode(__GLXclientState * cl,GLbyte * pc)108*4882a593Smuzhiyun __glXDisp_RenderMode(__GLXclientState * cl, GLbyte * pc)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun     ClientPtr client = cl->client;
111*4882a593Smuzhiyun     xGLXRenderModeReply reply;
112*4882a593Smuzhiyun     __GLXcontext *cx;
113*4882a593Smuzhiyun     GLint nitems = 0, retBytes = 0, retval, newModeCheck;
114*4882a593Smuzhiyun     GLubyte *retBuffer = NULL;
115*4882a593Smuzhiyun     GLenum newMode;
116*4882a593Smuzhiyun     int error;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
121*4882a593Smuzhiyun     if (!cx) {
122*4882a593Smuzhiyun         return error;
123*4882a593Smuzhiyun     }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun     pc += __GLX_SINGLE_HDR_SIZE;
126*4882a593Smuzhiyun     newMode = *(GLenum *) pc;
127*4882a593Smuzhiyun     retval = glRenderMode(newMode);
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun     /* Check that render mode worked */
130*4882a593Smuzhiyun     glGetIntegerv(GL_RENDER_MODE, &newModeCheck);
131*4882a593Smuzhiyun     if (newModeCheck != newMode) {
132*4882a593Smuzhiyun         /* Render mode change failed.  Bail */
133*4882a593Smuzhiyun         newMode = newModeCheck;
134*4882a593Smuzhiyun         goto noChangeAllowed;
135*4882a593Smuzhiyun     }
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     /*
138*4882a593Smuzhiyun      ** Render mode might have still failed if we get here.  But in this
139*4882a593Smuzhiyun      ** case we can't really tell, nor does it matter.  If it did fail, it
140*4882a593Smuzhiyun      ** will return 0, and thus we won't send any data across the wire.
141*4882a593Smuzhiyun      */
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     switch (cx->renderMode) {
144*4882a593Smuzhiyun     case GL_RENDER:
145*4882a593Smuzhiyun         cx->renderMode = newMode;
146*4882a593Smuzhiyun         break;
147*4882a593Smuzhiyun     case GL_FEEDBACK:
148*4882a593Smuzhiyun         if (retval < 0) {
149*4882a593Smuzhiyun             /* Overflow happened. Copy the entire buffer */
150*4882a593Smuzhiyun             nitems = cx->feedbackBufSize;
151*4882a593Smuzhiyun         }
152*4882a593Smuzhiyun         else {
153*4882a593Smuzhiyun             nitems = retval;
154*4882a593Smuzhiyun         }
155*4882a593Smuzhiyun         retBytes = nitems * __GLX_SIZE_FLOAT32;
156*4882a593Smuzhiyun         retBuffer = (GLubyte *) cx->feedbackBuf;
157*4882a593Smuzhiyun         cx->renderMode = newMode;
158*4882a593Smuzhiyun         break;
159*4882a593Smuzhiyun     case GL_SELECT:
160*4882a593Smuzhiyun         if (retval < 0) {
161*4882a593Smuzhiyun             /* Overflow happened.  Copy the entire buffer */
162*4882a593Smuzhiyun             nitems = cx->selectBufSize;
163*4882a593Smuzhiyun         }
164*4882a593Smuzhiyun         else {
165*4882a593Smuzhiyun             GLuint *bp = cx->selectBuf;
166*4882a593Smuzhiyun             GLint i;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun             /*
169*4882a593Smuzhiyun              ** Figure out how many bytes of data need to be sent.  Parse
170*4882a593Smuzhiyun              ** the selection buffer to determine this fact as the
171*4882a593Smuzhiyun              ** return value is the number of hits, not the number of
172*4882a593Smuzhiyun              ** items in the buffer.
173*4882a593Smuzhiyun              */
174*4882a593Smuzhiyun             nitems = 0;
175*4882a593Smuzhiyun             i = retval;
176*4882a593Smuzhiyun             while (--i >= 0) {
177*4882a593Smuzhiyun                 GLuint n;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun                 /* Parse select data for this hit */
180*4882a593Smuzhiyun                 n = *bp;
181*4882a593Smuzhiyun                 bp += 3 + n;
182*4882a593Smuzhiyun             }
183*4882a593Smuzhiyun             nitems = bp - cx->selectBuf;
184*4882a593Smuzhiyun         }
185*4882a593Smuzhiyun         retBytes = nitems * __GLX_SIZE_CARD32;
186*4882a593Smuzhiyun         retBuffer = (GLubyte *) cx->selectBuf;
187*4882a593Smuzhiyun         cx->renderMode = newMode;
188*4882a593Smuzhiyun         break;
189*4882a593Smuzhiyun     }
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun     /*
192*4882a593Smuzhiyun      ** First reply is the number of elements returned in the feedback or
193*4882a593Smuzhiyun      ** selection array, as per the API for glRenderMode itself.
194*4882a593Smuzhiyun      */
195*4882a593Smuzhiyun  noChangeAllowed:;
196*4882a593Smuzhiyun     reply = (xGLXRenderModeReply) {
197*4882a593Smuzhiyun         .type = X_Reply,
198*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
199*4882a593Smuzhiyun         .length = nitems,
200*4882a593Smuzhiyun         .retval = retval,
201*4882a593Smuzhiyun         .size = nitems,
202*4882a593Smuzhiyun         .newMode = newMode
203*4882a593Smuzhiyun     };
204*4882a593Smuzhiyun     WriteToClient(client, sz_xGLXRenderModeReply, &reply);
205*4882a593Smuzhiyun     if (retBytes) {
206*4882a593Smuzhiyun         WriteToClient(client, retBytes, retBuffer);
207*4882a593Smuzhiyun     }
208*4882a593Smuzhiyun     return Success;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun int
__glXDisp_Flush(__GLXclientState * cl,GLbyte * pc)212*4882a593Smuzhiyun __glXDisp_Flush(__GLXclientState * cl, GLbyte * pc)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun     ClientPtr client = cl->client;
215*4882a593Smuzhiyun     __GLXcontext *cx;
216*4882a593Smuzhiyun     int error;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xGLXSingleReq);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
221*4882a593Smuzhiyun     if (!cx) {
222*4882a593Smuzhiyun         return error;
223*4882a593Smuzhiyun     }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun     glFlush();
226*4882a593Smuzhiyun     return Success;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun int
__glXDisp_Finish(__GLXclientState * cl,GLbyte * pc)230*4882a593Smuzhiyun __glXDisp_Finish(__GLXclientState * cl, GLbyte * pc)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun     ClientPtr client = cl->client;
233*4882a593Smuzhiyun     __GLXcontext *cx;
234*4882a593Smuzhiyun     int error;
235*4882a593Smuzhiyun     xGLXSingleReply reply = { 0, };
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xGLXSingleReq);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
240*4882a593Smuzhiyun     if (!cx) {
241*4882a593Smuzhiyun         return error;
242*4882a593Smuzhiyun     }
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     /* Do a local glFinish */
245*4882a593Smuzhiyun     glFinish();
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun     /* Send empty reply packet to indicate finish is finished */
248*4882a593Smuzhiyun     client = cl->client;
249*4882a593Smuzhiyun     __GLX_BEGIN_REPLY(0);
250*4882a593Smuzhiyun     __GLX_SEND_HEADER();
251*4882a593Smuzhiyun     return Success;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun #define SEPARATOR " "
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun static char *
__glXcombine_strings(const char * cext_string,const char * sext_string)257*4882a593Smuzhiyun __glXcombine_strings(const char *cext_string, const char *sext_string)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun     size_t clen, slen;
260*4882a593Smuzhiyun     char *combo_string, *token, *s1;
261*4882a593Smuzhiyun     const char *s2, *end;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun     /* safeguard to prevent potentially fatal errors in the string functions */
264*4882a593Smuzhiyun     if (!cext_string)
265*4882a593Smuzhiyun         cext_string = "";
266*4882a593Smuzhiyun     if (!sext_string)
267*4882a593Smuzhiyun         sext_string = "";
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun     /*
270*4882a593Smuzhiyun      ** String can't be longer than min(cstring, sstring)
271*4882a593Smuzhiyun      ** pull tokens out of shortest string
272*4882a593Smuzhiyun      ** include space in combo_string for final separator and null terminator
273*4882a593Smuzhiyun      */
274*4882a593Smuzhiyun     clen = strlen(cext_string);
275*4882a593Smuzhiyun     slen = strlen(sext_string);
276*4882a593Smuzhiyun     if (clen > slen) {
277*4882a593Smuzhiyun         combo_string = (char *) malloc(slen + 2);
278*4882a593Smuzhiyun         s1 = (char *) malloc(slen + 2);
279*4882a593Smuzhiyun         if (s1)
280*4882a593Smuzhiyun             strcpy(s1, sext_string);
281*4882a593Smuzhiyun         s2 = cext_string;
282*4882a593Smuzhiyun     }
283*4882a593Smuzhiyun     else {
284*4882a593Smuzhiyun         combo_string = (char *) malloc(clen + 2);
285*4882a593Smuzhiyun         s1 = (char *) malloc(clen + 2);
286*4882a593Smuzhiyun         if (s1)
287*4882a593Smuzhiyun             strcpy(s1, cext_string);
288*4882a593Smuzhiyun         s2 = sext_string;
289*4882a593Smuzhiyun     }
290*4882a593Smuzhiyun     if (!combo_string || !s1) {
291*4882a593Smuzhiyun         free(combo_string);
292*4882a593Smuzhiyun         free(s1);
293*4882a593Smuzhiyun         return NULL;
294*4882a593Smuzhiyun     }
295*4882a593Smuzhiyun     combo_string[0] = '\0';
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun     /* Get first extension token */
298*4882a593Smuzhiyun     token = strtok(s1, SEPARATOR);
299*4882a593Smuzhiyun     while (token != NULL) {
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun         /*
302*4882a593Smuzhiyun          ** if token in second string then save it
303*4882a593Smuzhiyun          ** beware of extension names which are prefixes of other extension names
304*4882a593Smuzhiyun          */
305*4882a593Smuzhiyun         const char *p = s2;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun         end = p + strlen(p);
308*4882a593Smuzhiyun         while (p < end) {
309*4882a593Smuzhiyun             size_t n = strcspn(p, SEPARATOR);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun             if ((strlen(token) == n) && (strncmp(token, p, n) == 0)) {
312*4882a593Smuzhiyun                 combo_string = strcat(combo_string, token);
313*4882a593Smuzhiyun                 combo_string = strcat(combo_string, SEPARATOR);
314*4882a593Smuzhiyun             }
315*4882a593Smuzhiyun             p += (n + 1);
316*4882a593Smuzhiyun         }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun         /* Get next extension token */
319*4882a593Smuzhiyun         token = strtok(NULL, SEPARATOR);
320*4882a593Smuzhiyun     }
321*4882a593Smuzhiyun     free(s1);
322*4882a593Smuzhiyun     return combo_string;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun int
DoGetString(__GLXclientState * cl,GLbyte * pc,GLboolean need_swap)326*4882a593Smuzhiyun DoGetString(__GLXclientState * cl, GLbyte * pc, GLboolean need_swap)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun     ClientPtr client = cl->client;
329*4882a593Smuzhiyun     __GLXcontext *cx;
330*4882a593Smuzhiyun     GLenum name;
331*4882a593Smuzhiyun     const char *string;
332*4882a593Smuzhiyun     xGLXSingleReply reply = { 0, };
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun     __GLX_DECLARE_SWAP_VARIABLES;
335*4882a593Smuzhiyun     int error;
336*4882a593Smuzhiyun     char *buf = NULL, *buf1 = NULL;
337*4882a593Smuzhiyun     GLint length = 0;
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     /* If the client has the opposite byte order, swap the contextTag and
342*4882a593Smuzhiyun      * the name.
343*4882a593Smuzhiyun      */
344*4882a593Smuzhiyun     if (need_swap) {
345*4882a593Smuzhiyun         __GLX_SWAP_INT(pc + 4);
346*4882a593Smuzhiyun         __GLX_SWAP_INT(pc + __GLX_SINGLE_HDR_SIZE);
347*4882a593Smuzhiyun     }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
350*4882a593Smuzhiyun     if (!cx) {
351*4882a593Smuzhiyun         return error;
352*4882a593Smuzhiyun     }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun     pc += __GLX_SINGLE_HDR_SIZE;
355*4882a593Smuzhiyun     name = *(GLenum *) (pc + 0);
356*4882a593Smuzhiyun     string = (const char *) glGetString(name);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun     if (string == NULL)
359*4882a593Smuzhiyun         string = "";
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun     /*
362*4882a593Smuzhiyun      ** Restrict extensions to those that are supported by both the
363*4882a593Smuzhiyun      ** implementation and the connection.  That is, return the
364*4882a593Smuzhiyun      ** intersection of client, server, and core extension strings.
365*4882a593Smuzhiyun      */
366*4882a593Smuzhiyun     if (name == GL_EXTENSIONS) {
367*4882a593Smuzhiyun         buf1 = __glXcombine_strings(string, cl->GLClientextensions);
368*4882a593Smuzhiyun         buf = __glXcombine_strings(buf1, cx->pGlxScreen->GLextensions);
369*4882a593Smuzhiyun         free(buf1);
370*4882a593Smuzhiyun         string = buf;
371*4882a593Smuzhiyun     }
372*4882a593Smuzhiyun     else if (name == GL_VERSION) {
373*4882a593Smuzhiyun         if (atof(string) > atof(GLServerVersion)) {
374*4882a593Smuzhiyun             if (asprintf(&buf, "%s (%s)", GLServerVersion, string) == -1) {
375*4882a593Smuzhiyun                 string = GLServerVersion;
376*4882a593Smuzhiyun             }
377*4882a593Smuzhiyun             else {
378*4882a593Smuzhiyun                 string = buf;
379*4882a593Smuzhiyun             }
380*4882a593Smuzhiyun         }
381*4882a593Smuzhiyun     }
382*4882a593Smuzhiyun     if (string) {
383*4882a593Smuzhiyun         length = strlen((const char *) string) + 1;
384*4882a593Smuzhiyun     }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun     __GLX_BEGIN_REPLY(length);
387*4882a593Smuzhiyun     __GLX_PUT_SIZE(length);
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun     if (need_swap) {
390*4882a593Smuzhiyun         __GLX_SWAP_REPLY_SIZE();
391*4882a593Smuzhiyun         __GLX_SWAP_REPLY_HEADER();
392*4882a593Smuzhiyun     }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun     __GLX_SEND_HEADER();
395*4882a593Smuzhiyun     WriteToClient(client, length, string);
396*4882a593Smuzhiyun     free(buf);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun     return Success;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun int
__glXDisp_GetString(__GLXclientState * cl,GLbyte * pc)402*4882a593Smuzhiyun __glXDisp_GetString(__GLXclientState * cl, GLbyte * pc)
403*4882a593Smuzhiyun {
404*4882a593Smuzhiyun     return DoGetString(cl, pc, GL_FALSE);
405*4882a593Smuzhiyun }
406