Add mouse and keyboard configuration file
[profile/ivi/xorg-x11-server.git] / glx / single2.c
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 <stdio.h>
37 #include <stdlib.h>
38
39 #include "glxserver.h"
40 #include "glxutil.h"
41 #include "glxext.h"
42 #include "indirect_dispatch.h"
43 #include "unpack.h"
44 #include "glapitable.h"
45 #include "glapi.h"
46 #include "glthread.h"
47 #include "dispatch.h"
48
49 int __glXDisp_FeedbackBuffer(__GLXclientState *cl, GLbyte *pc)
50 {
51     GLsizei size;
52     GLenum type;
53     __GLXcontext *cx;
54     int error;
55
56     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
57     if (!cx) {
58         return error;
59     }
60
61     pc += __GLX_SINGLE_HDR_SIZE;
62     size = *(GLsizei *)(pc+0);
63     type = *(GLenum *)(pc+4);
64     if (cx->feedbackBufSize < size) {
65         cx->feedbackBuf = (GLfloat *) realloc(cx->feedbackBuf,
66                                                    (size_t)size 
67                                                    * __GLX_SIZE_FLOAT32);
68         if (!cx->feedbackBuf) {
69             cl->client->errorValue = size;
70             return BadAlloc;
71         }
72         cx->feedbackBufSize = size;
73     }
74     CALL_FeedbackBuffer( GET_DISPATCH(), (size, type, cx->feedbackBuf) );
75     __GLX_NOTE_UNFLUSHED_CMDS(cx);
76     return Success;
77 }
78
79 int __glXDisp_SelectBuffer(__GLXclientState *cl, GLbyte *pc)
80 {
81     __GLXcontext *cx;
82     GLsizei size;
83     int error;
84
85     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
86     if (!cx) {
87         return error;
88     }
89
90     pc += __GLX_SINGLE_HDR_SIZE;
91     size = *(GLsizei *)(pc+0);
92     if (cx->selectBufSize < size) {
93         cx->selectBuf = (GLuint *) realloc(cx->selectBuf,
94                                                 (size_t) size 
95                                                 * __GLX_SIZE_CARD32);
96         if (!cx->selectBuf) {
97             cl->client->errorValue = size;
98             return BadAlloc;
99         }
100         cx->selectBufSize = size;
101     }
102     CALL_SelectBuffer( GET_DISPATCH(), (size, cx->selectBuf) );
103     __GLX_NOTE_UNFLUSHED_CMDS(cx);
104     return Success;
105 }
106
107 int __glXDisp_RenderMode(__GLXclientState *cl, GLbyte *pc)
108 {
109     ClientPtr client;
110     xGLXRenderModeReply reply;
111     __GLXcontext *cx;
112     GLint nitems=0, retBytes=0, retval, newModeCheck;
113     GLubyte *retBuffer = NULL;
114     GLenum newMode;
115     int error;
116
117     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
118     if (!cx) {
119         return error;
120     }
121
122     pc += __GLX_SINGLE_HDR_SIZE;
123     newMode = *(GLenum*) pc;
124     retval = CALL_RenderMode( GET_DISPATCH(), (newMode) );
125
126     /* Check that render mode worked */
127     CALL_GetIntegerv( GET_DISPATCH(), (GL_RENDER_MODE, &newModeCheck) );
128     if (newModeCheck != newMode) {
129         /* Render mode change failed.  Bail */
130         newMode = newModeCheck;
131         goto noChangeAllowed;
132     }
133
134     /*
135     ** Render mode might have still failed if we get here.  But in this
136     ** case we can't really tell, nor does it matter.  If it did fail, it
137     ** will return 0, and thus we won't send any data across the wire.
138     */
139
140     switch (cx->renderMode) {
141       case GL_RENDER:
142         cx->renderMode = newMode;
143         break;
144       case GL_FEEDBACK:
145         if (retval < 0) {
146             /* Overflow happened. Copy the entire buffer */
147             nitems = cx->feedbackBufSize;
148         } else {
149             nitems = retval;
150         }
151         retBytes = nitems * __GLX_SIZE_FLOAT32;
152         retBuffer = (GLubyte*) cx->feedbackBuf;
153         cx->renderMode = newMode;
154         break;
155       case GL_SELECT:
156         if (retval < 0) {
157             /* Overflow happened.  Copy the entire buffer */
158             nitems = cx->selectBufSize;
159         } else {
160             GLuint *bp = cx->selectBuf;
161             GLint i;
162
163             /*
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.
168             */
169             nitems = 0;
170             i = retval;
171             while (--i >= 0) {
172                 GLuint n;
173
174                 /* Parse select data for this hit */
175                 n = *bp;
176                 bp += 3 + n;
177             }
178             nitems = bp - cx->selectBuf;
179         }
180         retBytes = nitems * __GLX_SIZE_CARD32;
181         retBuffer = (GLubyte*) cx->selectBuf;
182         cx->renderMode = newMode;
183         break;
184     }
185
186     /*
187     ** First reply is the number of elements returned in the feedback or
188     ** selection array, as per the API for glRenderMode itself.
189     */
190   noChangeAllowed:;
191     client = cl->client;
192     reply.length = nitems;
193     reply.type = X_Reply;
194     reply.sequenceNumber = client->sequence;
195     reply.retval = retval;
196     reply.size = nitems;
197     reply.newMode = newMode;
198     WriteToClient(client, sz_xGLXRenderModeReply, (char *)&reply);
199     if (retBytes) {
200         WriteToClient(client, retBytes, (char *)retBuffer);
201     }
202     return Success;
203 }
204
205 int __glXDisp_Flush(__GLXclientState *cl, GLbyte *pc)
206 {
207         __GLXcontext *cx;
208         int error;
209
210         cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
211         if (!cx) {
212                 return error;
213         }
214
215         CALL_Flush( GET_DISPATCH(), () );
216         __GLX_NOTE_FLUSHED_CMDS(cx);
217         return Success;
218 }
219
220 int __glXDisp_Finish(__GLXclientState *cl, GLbyte *pc)
221 {
222     __GLXcontext *cx;
223     ClientPtr client;
224     int error;
225
226     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
227     if (!cx) {
228         return error;
229     }
230
231     /* Do a local glFinish */
232     CALL_Finish( GET_DISPATCH(), () );
233     __GLX_NOTE_FLUSHED_CMDS(cx);
234
235     /* Send empty reply packet to indicate finish is finished */
236     client = cl->client;
237     __GLX_BEGIN_REPLY(0);
238     __GLX_SEND_HEADER();
239     return Success;
240 }
241
242 #define SEPARATOR " "
243
244 char *__glXcombine_strings(const char *cext_string, const char *sext_string)
245 {
246    size_t clen, slen;
247    char *combo_string, *token, *s1;
248    const char *s2, *end;
249
250    /* safeguard to prevent potentially fatal errors in the string functions */
251    if (!cext_string)
252       cext_string = "";
253    if (!sext_string)
254       sext_string = "";
255
256    /*
257    ** String can't be longer than min(cstring, sstring)
258    ** pull tokens out of shortest string
259    ** include space in combo_string for final separator and null terminator
260    */
261    clen = strlen(cext_string);
262    slen = strlen(sext_string);
263    if (clen > slen) {
264         combo_string = (char *) malloc(slen + 2);
265         s1 = (char *) malloc(slen + 2);
266         if (s1) strcpy(s1, sext_string);
267         s2 = cext_string;
268    } else {
269         combo_string = (char *) malloc(clen + 2);
270         s1 = (char *) malloc(clen + 2);
271         if (s1) strcpy(s1, cext_string);
272         s2 = sext_string;
273    }
274    if (!combo_string || !s1) {
275         free(combo_string);
276         free(s1);
277         return NULL;
278    }
279    combo_string[0] = '\0';
280
281    /* Get first extension token */
282    token = strtok( s1, SEPARATOR);
283    while ( token != NULL ) {
284
285         /*
286         ** if token in second string then save it
287         ** beware of extension names which are prefixes of other extension names
288         */
289         const char *p = s2;
290         end = p + strlen(p);
291         while (p < end) {
292             size_t n = strcspn(p, SEPARATOR);
293             if ((strlen(token) == n) && (strncmp(token, p, n) == 0)) {
294                 combo_string = strcat(combo_string, token);
295                 combo_string = strcat(combo_string, SEPARATOR);
296             }
297             p += (n + 1);
298         }
299
300         /* Get next extension token */
301         token = strtok( NULL, SEPARATOR);
302    }
303    free(s1);
304    return combo_string;
305 }
306
307 int DoGetString(__GLXclientState *cl, GLbyte *pc, GLboolean need_swap)
308 {
309     ClientPtr client;
310     __GLXcontext *cx;
311     GLenum name;
312     const char *string;
313     __GLX_DECLARE_SWAP_VARIABLES;
314     int error;
315     char *buf = NULL, *buf1 = NULL;
316     GLint length = 0;
317
318     /* If the client has the opposite byte order, swap the contextTag and
319      * the name.
320      */
321     if ( need_swap ) {
322         __GLX_SWAP_INT(pc + 4);
323         __GLX_SWAP_INT(pc + __GLX_SINGLE_HDR_SIZE);
324     }
325
326     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
327     if (!cx) {
328         return error;
329     }
330
331     pc += __GLX_SINGLE_HDR_SIZE;
332     name = *(GLenum *)(pc + 0);
333     string = (const char *) CALL_GetString( GET_DISPATCH(), (name) );
334     client = cl->client;
335
336     if (string == NULL)
337       string = "";
338
339     /*
340     ** Restrict extensions to those that are supported by both the
341     ** implementation and the connection.  That is, return the
342     ** intersection of client, server, and core extension strings.
343     */
344     if (name == GL_EXTENSIONS) {
345         buf1 = __glXcombine_strings(string,
346                                       cl->GLClientextensions);
347         buf = __glXcombine_strings(buf1,
348                                       cx->pGlxScreen->GLextensions);
349         if (buf1 != NULL) {
350             free(buf1);
351         }
352         string = buf;
353     }
354     else if ( name == GL_VERSION ) {
355         if ( atof( string ) > atof( GLServerVersion ) ) {
356             buf = malloc( strlen( string ) + strlen( GLServerVersion ) + 4 );
357             if ( buf == NULL ) {
358                 string = GLServerVersion;
359             }
360             else {
361                 sprintf( buf, "%s (%s)", GLServerVersion, string );
362                 string = buf;
363             }
364         }
365     }
366     if (string) {
367         length = strlen((const char *) string) + 1;
368     }
369
370     __GLX_BEGIN_REPLY(length);
371     __GLX_PUT_SIZE(length);
372
373     if ( need_swap ) {
374         __GLX_SWAP_REPLY_SIZE();
375         __GLX_SWAP_REPLY_HEADER();
376     }
377
378     __GLX_SEND_HEADER();
379     WriteToClient(client, length, (char *) string); 
380     if (buf != NULL)
381         free(buf);
382
383     return Success;
384 }
385
386 int __glXDisp_GetString(__GLXclientState *cl, GLbyte *pc)
387 {
388     return DoGetString(cl, pc, GL_FALSE);
389 }