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