2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
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:
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.
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
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.
31 #ifdef HAVE_DIX_CONFIG_H
32 #include <dix-config.h>
39 #include "glxserver.h"
42 #include "indirect_dispatch.h"
46 __glXDisp_FeedbackBuffer(__GLXclientState
* cl
, GLbyte
* pc
)
53 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
58 pc
+= __GLX_SINGLE_HDR_SIZE
;
59 size
= *(GLsizei
*) (pc
+ 0);
60 type
= *(GLenum
*) (pc
+ 4);
61 if (cx
->feedbackBufSize
< size
) {
62 cx
->feedbackBuf
= (GLfloat
*) realloc(cx
->feedbackBuf
,
64 * __GLX_SIZE_FLOAT32
);
65 if (!cx
->feedbackBuf
) {
66 cl
->client
->errorValue
= size
;
69 cx
->feedbackBufSize
= size
;
71 glFeedbackBuffer(size
, type
, cx
->feedbackBuf
);
72 cx
->hasUnflushedCommands
= GL_TRUE
;
77 __glXDisp_SelectBuffer(__GLXclientState
* cl
, GLbyte
* pc
)
83 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
88 pc
+= __GLX_SINGLE_HDR_SIZE
;
89 size
= *(GLsizei
*) (pc
+ 0);
90 if (cx
->selectBufSize
< size
) {
91 cx
->selectBuf
= (GLuint
*) realloc(cx
->selectBuf
,
92 (size_t) size
* __GLX_SIZE_CARD32
);
94 cl
->client
->errorValue
= size
;
97 cx
->selectBufSize
= size
;
99 glSelectBuffer(size
, cx
->selectBuf
);
100 cx
->hasUnflushedCommands
= GL_TRUE
;
105 __glXDisp_RenderMode(__GLXclientState
* cl
, GLbyte
* pc
)
108 xGLXRenderModeReply reply
;
110 GLint nitems
= 0, retBytes
= 0, retval
, newModeCheck
;
111 GLubyte
*retBuffer
= NULL
;
115 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
120 pc
+= __GLX_SINGLE_HDR_SIZE
;
121 newMode
= *(GLenum
*) pc
;
122 retval
= glRenderMode(newMode
);
124 /* Check that render mode worked */
125 glGetIntegerv(GL_RENDER_MODE
, &newModeCheck
);
126 if (newModeCheck
!= newMode
) {
127 /* Render mode change failed. Bail */
128 newMode
= newModeCheck
;
129 goto noChangeAllowed
;
133 ** Render mode might have still failed if we get here. But in this
134 ** case we can't really tell, nor does it matter. If it did fail, it
135 ** will return 0, and thus we won't send any data across the wire.
138 switch (cx
->renderMode
) {
140 cx
->renderMode
= newMode
;
144 /* Overflow happened. Copy the entire buffer */
145 nitems
= cx
->feedbackBufSize
;
150 retBytes
= nitems
* __GLX_SIZE_FLOAT32
;
151 retBuffer
= (GLubyte
*) cx
->feedbackBuf
;
152 cx
->renderMode
= newMode
;
156 /* Overflow happened. Copy the entire buffer */
157 nitems
= cx
->selectBufSize
;
160 GLuint
*bp
= cx
->selectBuf
;
164 ** Figure out how many bytes of data need to be sent. Parse
165 ** the selection buffer to determine this fact as the
166 ** return value is the number of hits, not the number of
167 ** items in the buffer.
174 /* Parse select data for this hit */
178 nitems
= bp
- cx
->selectBuf
;
180 retBytes
= nitems
* __GLX_SIZE_CARD32
;
181 retBuffer
= (GLubyte
*) cx
->selectBuf
;
182 cx
->renderMode
= newMode
;
187 ** First reply is the number of elements returned in the feedback or
188 ** selection array, as per the API for glRenderMode itself.
192 reply
= (xGLXRenderModeReply
) {
194 .sequenceNumber
= client
->sequence
,
200 WriteToClient(client
, sz_xGLXRenderModeReply
, &reply
);
202 WriteToClient(client
, retBytes
, retBuffer
);
208 __glXDisp_Flush(__GLXclientState
* cl
, GLbyte
* pc
)
213 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
219 cx
->hasUnflushedCommands
= GL_FALSE
;
224 __glXDisp_Finish(__GLXclientState
* cl
, GLbyte
* pc
)
230 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
235 /* Do a local glFinish */
237 cx
->hasUnflushedCommands
= GL_FALSE
;
239 /* Send empty reply packet to indicate finish is finished */
241 __GLX_BEGIN_REPLY(0);
246 #define SEPARATOR " "
249 __glXcombine_strings(const char *cext_string
, const char *sext_string
)
252 char *combo_string
, *token
, *s1
;
253 const char *s2
, *end
;
255 /* safeguard to prevent potentially fatal errors in the string functions */
262 ** String can't be longer than min(cstring, sstring)
263 ** pull tokens out of shortest string
264 ** include space in combo_string for final separator and null terminator
266 clen
= strlen(cext_string
);
267 slen
= strlen(sext_string
);
269 combo_string
= (char *) malloc(slen
+ 2);
270 s1
= (char *) malloc(slen
+ 2);
272 strcpy(s1
, sext_string
);
276 combo_string
= (char *) malloc(clen
+ 2);
277 s1
= (char *) malloc(clen
+ 2);
279 strcpy(s1
, cext_string
);
282 if (!combo_string
|| !s1
) {
287 combo_string
[0] = '\0';
289 /* Get first extension token */
290 token
= strtok(s1
, SEPARATOR
);
291 while (token
!= NULL
) {
294 ** if token in second string then save it
295 ** beware of extension names which are prefixes of other extension names
301 size_t n
= strcspn(p
, SEPARATOR
);
303 if ((strlen(token
) == n
) && (strncmp(token
, p
, n
) == 0)) {
304 combo_string
= strcat(combo_string
, token
);
305 combo_string
= strcat(combo_string
, SEPARATOR
);
310 /* Get next extension token */
311 token
= strtok(NULL
, SEPARATOR
);
318 DoGetString(__GLXclientState
* cl
, GLbyte
* pc
, GLboolean need_swap
)
325 __GLX_DECLARE_SWAP_VARIABLES
;
327 char *buf
= NULL
, *buf1
= NULL
;
330 /* If the client has the opposite byte order, swap the contextTag and
334 __GLX_SWAP_INT(pc
+ 4);
335 __GLX_SWAP_INT(pc
+ __GLX_SINGLE_HDR_SIZE
);
338 cx
= __glXForceCurrent(cl
, __GLX_GET_SINGLE_CONTEXT_TAG(pc
), &error
);
343 pc
+= __GLX_SINGLE_HDR_SIZE
;
344 name
= *(GLenum
*) (pc
+ 0);
345 string
= (const char *) glGetString(name
);
352 ** Restrict extensions to those that are supported by both the
353 ** implementation and the connection. That is, return the
354 ** intersection of client, server, and core extension strings.
356 if (name
== GL_EXTENSIONS
) {
357 buf1
= __glXcombine_strings(string
, cl
->GLClientextensions
);
358 buf
= __glXcombine_strings(buf1
, cx
->pGlxScreen
->GLextensions
);
362 else if (name
== GL_VERSION
) {
363 if (atof(string
) > atof(GLServerVersion
)) {
364 if (asprintf(&buf
, "%s (%s)", GLServerVersion
, string
) == -1) {
365 string
= GLServerVersion
;
373 length
= strlen((const char *) string
) + 1;
376 __GLX_BEGIN_REPLY(length
);
377 __GLX_PUT_SIZE(length
);
380 __GLX_SWAP_REPLY_SIZE();
381 __GLX_SWAP_REPLY_HEADER();
385 WriteToClient(client
, length
, string
);
392 __glXDisp_GetString(__GLXclientState
* cl
, GLbyte
* pc
)
394 return DoGetString(cl
, pc
, GL_FALSE
);