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