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