single2swap.c revision 7e31ba66
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    return Success;
76}
77
78int
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
112int
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
228int
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
249int
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
279int
280__glXDispSwap_GetString(__GLXclientState * cl, GLbyte * pc)
281{
282    return DoGetString(cl, pc, GL_TRUE);
283}
284