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