single2swap.c revision 706f2543
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    ClientPtr client = cl->client;
48    GLsizei size;
49    GLenum type;
50    __GLX_DECLARE_SWAP_VARIABLES;
51    __GLXcontext *cx;
52    int error;
53
54    REQUEST_FIXED_SIZE(xGLXSingleReq, 8);
55
56    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
57    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
58    if (!cx) {
59	return error;
60    }
61
62    pc += __GLX_SINGLE_HDR_SIZE;
63    __GLX_SWAP_INT(pc+0);
64    __GLX_SWAP_INT(pc+4);
65    size = *(GLsizei *)(pc+0);
66    type = *(GLenum *)(pc+4);
67    if (cx->feedbackBufSize < size) {
68	cx->feedbackBuf = (GLfloat *) realloc(cx->feedbackBuf,
69						   (size_t) size
70						   * __GLX_SIZE_FLOAT32);
71	if (!cx->feedbackBuf) {
72	    cl->client->errorValue = size;
73	    return BadAlloc;
74	}
75	cx->feedbackBufSize = size;
76    }
77    CALL_FeedbackBuffer( GET_DISPATCH(), (size, type, cx->feedbackBuf) );
78    __GLX_NOTE_UNFLUSHED_CMDS(cx);
79    return Success;
80}
81
82int __glXDispSwap_SelectBuffer(__GLXclientState *cl, GLbyte *pc)
83{
84    ClientPtr client = cl->client;
85    __GLXcontext *cx;
86    GLsizei size;
87    __GLX_DECLARE_SWAP_VARIABLES;
88    int error;
89
90    REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
91
92    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
93    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
94    if (!cx) {
95	return error;
96    }
97
98    pc += __GLX_SINGLE_HDR_SIZE;
99    __GLX_SWAP_INT(pc+0);
100    size = *(GLsizei *)(pc+0);
101    if (cx->selectBufSize < size) {
102	cx->selectBuf = (GLuint *) realloc(cx->selectBuf,
103						(size_t) size
104						* __GLX_SIZE_CARD32);
105	if (!cx->selectBuf) {
106	    cl->client->errorValue = size;
107	    return BadAlloc;
108	}
109	cx->selectBufSize = size;
110    }
111    CALL_SelectBuffer( GET_DISPATCH(), (size, cx->selectBuf) );
112    __GLX_NOTE_UNFLUSHED_CMDS(cx);
113    return Success;
114}
115
116int __glXDispSwap_RenderMode(__GLXclientState *cl, GLbyte *pc)
117{
118    ClientPtr client = cl->client;
119    __GLXcontext *cx;
120    xGLXRenderModeReply reply;
121    GLint nitems=0, retBytes=0, retval, newModeCheck;
122    GLubyte *retBuffer = NULL;
123    GLenum newMode;
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 = CALL_RenderMode( GET_DISPATCH(), (newMode) );
140
141    /* Check that render mode worked */
142    CALL_GetIntegerv( GET_DISPATCH(), (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	} else {
164	    nitems = retval;
165	}
166	retBytes = nitems * __GLX_SIZE_FLOAT32;
167	retBuffer = (GLubyte*) cx->feedbackBuf;
168	__GLX_SWAP_FLOAT_ARRAY((GLbyte *)retBuffer, nitems);
169	cx->renderMode = newMode;
170	break;
171      case GL_SELECT:
172	if (retval < 0) {
173	    /* Overflow happened.  Copy the entire buffer */
174	    nitems = cx->selectBufSize;
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.length = nitems;
209    reply.type = X_Reply;
210    reply.sequenceNumber = client->sequence;
211    reply.retval = retval;
212    reply.size = nitems;
213    reply.newMode = newMode;
214    __GLX_SWAP_SHORT(&reply.sequenceNumber);
215    __GLX_SWAP_INT(&reply.length);
216    __GLX_SWAP_INT(&reply.retval);
217    __GLX_SWAP_INT(&reply.size);
218    __GLX_SWAP_INT(&reply.newMode);
219    WriteToClient(client, sz_xGLXRenderModeReply, (char *)&reply);
220    if (retBytes) {
221	WriteToClient(client, retBytes, (char *)retBuffer);
222    }
223    return Success;
224}
225
226int __glXDispSwap_Flush(__GLXclientState *cl, GLbyte *pc)
227{
228	ClientPtr client = cl->client;
229	__GLXcontext *cx;
230	int error;
231	__GLX_DECLARE_SWAP_VARIABLES;
232
233	REQUEST_SIZE_MATCH(xGLXSingleReq);
234
235	__GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
236	cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
237	if (!cx) {
238		return error;
239	}
240
241	CALL_Flush( GET_DISPATCH(), () );
242	__GLX_NOTE_FLUSHED_CMDS(cx);
243	return Success;
244}
245
246int __glXDispSwap_Finish(__GLXclientState *cl, GLbyte *pc)
247{
248    ClientPtr client = cl->client;
249    __GLXcontext *cx;
250    int error;
251    __GLX_DECLARE_SWAP_VARIABLES;
252
253    REQUEST_SIZE_MATCH(xGLXSingleReq);
254
255    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
256    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
257    if (!cx) {
258	return error;
259    }
260
261    /* Do a local glFinish */
262    CALL_Finish( GET_DISPATCH(), () );
263    __GLX_NOTE_FLUSHED_CMDS(cx);
264
265    /* Send empty reply packet to indicate finish is finished */
266    __GLX_BEGIN_REPLY(0);
267    __GLX_PUT_RETVAL(0);
268    __GLX_SWAP_REPLY_HEADER();
269    __GLX_SEND_HEADER();
270
271    return Success;
272}
273
274int __glXDispSwap_GetString(__GLXclientState *cl, GLbyte *pc)
275{
276    return DoGetString(cl, pc, GL_TRUE);
277}
278