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 "glxserver.h"
36 #include "glxutil.h"
37 #include "glxext.h"
38 #include "indirect_dispatch.h"
39 #include "unpack.h"
40 
41 int
__glXDispSwap_FeedbackBuffer(__GLXclientState * cl,GLbyte * pc)42 __glXDispSwap_FeedbackBuffer(__GLXclientState * cl, GLbyte * pc)
43 {
44     ClientPtr client = cl->client;
45     GLsizei size;
46     GLenum type;
47 
48     __GLX_DECLARE_SWAP_VARIABLES;
49     __GLXcontext *cx;
50     int error;
51 
52     REQUEST_FIXED_SIZE(xGLXSingleReq, 8);
53 
54     __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag);
55     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
56     if (!cx) {
57         return error;
58     }
59 
60     pc += __GLX_SINGLE_HDR_SIZE;
61     __GLX_SWAP_INT(pc + 0);
62     __GLX_SWAP_INT(pc + 4);
63     size = *(GLsizei *) (pc + 0);
64     type = *(GLenum *) (pc + 4);
65     if (cx->feedbackBufSize < size) {
66         cx->feedbackBuf = reallocarray(cx->feedbackBuf,
67                                        (size_t) size, __GLX_SIZE_FLOAT32);
68         if (!cx->feedbackBuf) {
69             cl->client->errorValue = size;
70             return BadAlloc;
71         }
72         cx->feedbackBufSize = size;
73     }
74     glFeedbackBuffer(size, type, cx->feedbackBuf);
75     return Success;
76 }
77 
78 int
__glXDispSwap_SelectBuffer(__GLXclientState * cl,GLbyte * pc)79 __glXDispSwap_SelectBuffer(__GLXclientState * cl, GLbyte * pc)
80 {
81     ClientPtr client = cl->client;
82     __GLXcontext *cx;
83     GLsizei size;
84 
85     __GLX_DECLARE_SWAP_VARIABLES;
86     int error;
87 
88     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
89 
90     __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag);
91     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
92     if (!cx) {
93         return error;
94     }
95 
96     pc += __GLX_SINGLE_HDR_SIZE;
97     __GLX_SWAP_INT(pc + 0);
98     size = *(GLsizei *) (pc + 0);
99     if (cx->selectBufSize < size) {
100         cx->selectBuf = reallocarray(cx->selectBuf,
101                                      (size_t) size, __GLX_SIZE_CARD32);
102         if (!cx->selectBuf) {
103             cl->client->errorValue = size;
104             return BadAlloc;
105         }
106         cx->selectBufSize = size;
107     }
108     glSelectBuffer(size, cx->selectBuf);
109     return Success;
110 }
111 
112 int
__glXDispSwap_RenderMode(__GLXclientState * cl,GLbyte * pc)113 __glXDispSwap_RenderMode(__GLXclientState * cl, GLbyte * pc)
114 {
115     ClientPtr client = cl->client;
116     __GLXcontext *cx;
117     xGLXRenderModeReply reply;
118     GLint nitems = 0, retBytes = 0, retval, newModeCheck;
119     GLubyte *retBuffer = NULL;
120     GLenum newMode;
121 
122     __GLX_DECLARE_SWAP_VARIABLES;
123     __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
124     int error;
125 
126     REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
127 
128     __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag);
129     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
130     if (!cx) {
131         return error;
132     }
133 
134     pc += __GLX_SINGLE_HDR_SIZE;
135     __GLX_SWAP_INT(pc);
136     newMode = *(GLenum *) pc;
137     retval = glRenderMode(newMode);
138 
139     /* Check that render mode worked */
140     glGetIntegerv(GL_RENDER_MODE, &newModeCheck);
141     if (newModeCheck != newMode) {
142         /* Render mode change failed.  Bail */
143         newMode = newModeCheck;
144         goto noChangeAllowed;
145     }
146 
147     /*
148      ** Render mode might have still failed if we get here.  But in this
149      ** case we can't really tell, nor does it matter.  If it did fail, it
150      ** will return 0, and thus we won't send any data across the wire.
151      */
152 
153     switch (cx->renderMode) {
154     case GL_RENDER:
155         cx->renderMode = newMode;
156         break;
157     case GL_FEEDBACK:
158         if (retval < 0) {
159             /* Overflow happened. Copy the entire buffer */
160             nitems = cx->feedbackBufSize;
161         }
162         else {
163             nitems = retval;
164         }
165         retBytes = nitems * __GLX_SIZE_FLOAT32;
166         retBuffer = (GLubyte *) cx->feedbackBuf;
167         __GLX_SWAP_FLOAT_ARRAY((GLbyte *) retBuffer, nitems);
168         cx->renderMode = newMode;
169         break;
170     case GL_SELECT:
171         if (retval < 0) {
172             /* Overflow happened.  Copy the entire buffer */
173             nitems = cx->selectBufSize;
174         }
175         else {
176             GLuint *bp = cx->selectBuf;
177             GLint i;
178 
179             /*
180              ** Figure out how many bytes of data need to be sent.  Parse
181              ** the selection buffer to determine this fact as the
182              ** return value is the number of hits, not the number of
183              ** items in the buffer.
184              */
185             nitems = 0;
186             i = retval;
187             while (--i >= 0) {
188                 GLuint n;
189 
190                 /* Parse select data for this hit */
191                 n = *bp;
192                 bp += 3 + n;
193             }
194             nitems = bp - cx->selectBuf;
195         }
196         retBytes = nitems * __GLX_SIZE_CARD32;
197         retBuffer = (GLubyte *) cx->selectBuf;
198         __GLX_SWAP_INT_ARRAY((GLbyte *) retBuffer, nitems);
199         cx->renderMode = newMode;
200         break;
201     }
202 
203     /*
204      ** First reply is the number of elements returned in the feedback or
205      ** selection array, as per the API for glRenderMode itself.
206      */
207  noChangeAllowed:;
208     reply = (xGLXRenderModeReply) {
209         .type = X_Reply,
210         .sequenceNumber = client->sequence,
211         .length = nitems,
212         .retval = retval,
213         .size = nitems,
214         .newMode = newMode
215     };
216     __GLX_SWAP_SHORT(&reply.sequenceNumber);
217     __GLX_SWAP_INT(&reply.length);
218     __GLX_SWAP_INT(&reply.retval);
219     __GLX_SWAP_INT(&reply.size);
220     __GLX_SWAP_INT(&reply.newMode);
221     WriteToClient(client, sz_xGLXRenderModeReply, &reply);
222     if (retBytes) {
223         WriteToClient(client, retBytes, retBuffer);
224     }
225     return Success;
226 }
227 
228 int
__glXDispSwap_Flush(__GLXclientState * cl,GLbyte * pc)229 __glXDispSwap_Flush(__GLXclientState * cl, GLbyte * pc)
230 {
231     ClientPtr client = cl->client;
232     __GLXcontext *cx;
233     int error;
234 
235     __GLX_DECLARE_SWAP_VARIABLES;
236 
237     REQUEST_SIZE_MATCH(xGLXSingleReq);
238 
239     __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag);
240     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
241     if (!cx) {
242         return error;
243     }
244 
245     glFlush();
246     return Success;
247 }
248 
249 int
__glXDispSwap_Finish(__GLXclientState * cl,GLbyte * pc)250 __glXDispSwap_Finish(__GLXclientState * cl, GLbyte * pc)
251 {
252     ClientPtr client = cl->client;
253     __GLXcontext *cx;
254     int error;
255     xGLXSingleReply reply = { 0, };
256 
257     __GLX_DECLARE_SWAP_VARIABLES;
258 
259     REQUEST_SIZE_MATCH(xGLXSingleReq);
260 
261     __GLX_SWAP_INT(&((xGLXSingleReq *) pc)->contextTag);
262     cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
263     if (!cx) {
264         return error;
265     }
266 
267     /* Do a local glFinish */
268     glFinish();
269 
270     /* Send empty reply packet to indicate finish is finished */
271     __GLX_BEGIN_REPLY(0);
272     __GLX_PUT_RETVAL(0);
273     __GLX_SWAP_REPLY_HEADER();
274     __GLX_SEND_HEADER();
275 
276     return Success;
277 }
278 
279 int
__glXDispSwap_GetString(__GLXclientState * cl,GLbyte * pc)280 __glXDispSwap_GetString(__GLXclientState * cl, GLbyte * pc)
281 {
282     return DoGetString(cl, pc, GL_TRUE);
283 }
284