single2swap.c revision 0b0d8713
14642e01fSmrg/*
24642e01fSmrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
34642e01fSmrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
44642e01fSmrg *
54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
64642e01fSmrg * copy of this software and associated documentation files (the "Software"),
74642e01fSmrg * to deal in the Software without restriction, including without limitation
84642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
94642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
104642e01fSmrg * Software is furnished to do so, subject to the following conditions:
114642e01fSmrg *
124642e01fSmrg * The above copyright notice including the dates of first publication and
134642e01fSmrg * either this permission notice or a reference to
144642e01fSmrg * http://oss.sgi.com/projects/FreeB/
154642e01fSmrg * shall be included in all copies or substantial portions of the Software.
164642e01fSmrg *
174642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
184642e01fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
194642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
204642e01fSmrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
214642e01fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
224642e01fSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
234642e01fSmrg * SOFTWARE.
244642e01fSmrg *
254642e01fSmrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
264642e01fSmrg * shall not be used in advertising or otherwise to promote the sale, use or
274642e01fSmrg * other dealings in this Software without prior written authorization from
284642e01fSmrg * Silicon Graphics, Inc.
294642e01fSmrg */
304642e01fSmrg
314642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
324642e01fSmrg#include <dix-config.h>
334642e01fSmrg#endif
344642e01fSmrg
354642e01fSmrg#include "glxserver.h"
364642e01fSmrg#include "glxutil.h"
374642e01fSmrg#include "glxext.h"
384642e01fSmrg#include "indirect_dispatch.h"
394642e01fSmrg#include "unpack.h"
404642e01fSmrg#include "glapitable.h"
414642e01fSmrg#include "glapi.h"
424642e01fSmrg#include "glthread.h"
434642e01fSmrg#include "dispatch.h"
444642e01fSmrg
454642e01fSmrgint __glXDispSwap_FeedbackBuffer(__GLXclientState *cl, GLbyte *pc)
464642e01fSmrg{
470b0d8713Smrg    ClientPtr client = cl->client;
484642e01fSmrg    GLsizei size;
494642e01fSmrg    GLenum type;
504642e01fSmrg    __GLX_DECLARE_SWAP_VARIABLES;
514642e01fSmrg    __GLXcontext *cx;
524642e01fSmrg    int error;
534642e01fSmrg
540b0d8713Smrg    REQUEST_FIXED_SIZE(xGLXSingleReq, 8);
550b0d8713Smrg
564642e01fSmrg    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
574642e01fSmrg    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
584642e01fSmrg    if (!cx) {
594642e01fSmrg	return error;
604642e01fSmrg    }
614642e01fSmrg
624642e01fSmrg    pc += __GLX_SINGLE_HDR_SIZE;
634642e01fSmrg    __GLX_SWAP_INT(pc+0);
644642e01fSmrg    __GLX_SWAP_INT(pc+4);
654642e01fSmrg    size = *(GLsizei *)(pc+0);
664642e01fSmrg    type = *(GLenum *)(pc+4);
674642e01fSmrg    if (cx->feedbackBufSize < size) {
686747b715Smrg	cx->feedbackBuf = (GLfloat *) realloc(cx->feedbackBuf,
694642e01fSmrg						   (size_t) size
704642e01fSmrg						   * __GLX_SIZE_FLOAT32);
714642e01fSmrg	if (!cx->feedbackBuf) {
724642e01fSmrg	    cl->client->errorValue = size;
734642e01fSmrg	    return BadAlloc;
744642e01fSmrg	}
754642e01fSmrg	cx->feedbackBufSize = size;
764642e01fSmrg    }
774642e01fSmrg    CALL_FeedbackBuffer( GET_DISPATCH(), (size, type, cx->feedbackBuf) );
784642e01fSmrg    __GLX_NOTE_UNFLUSHED_CMDS(cx);
794642e01fSmrg    return Success;
804642e01fSmrg}
814642e01fSmrg
824642e01fSmrgint __glXDispSwap_SelectBuffer(__GLXclientState *cl, GLbyte *pc)
834642e01fSmrg{
840b0d8713Smrg    ClientPtr client = cl->client;
854642e01fSmrg    __GLXcontext *cx;
864642e01fSmrg    GLsizei size;
874642e01fSmrg    __GLX_DECLARE_SWAP_VARIABLES;
884642e01fSmrg    int error;
894642e01fSmrg
900b0d8713Smrg    REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
910b0d8713Smrg
924642e01fSmrg    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
934642e01fSmrg    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
944642e01fSmrg    if (!cx) {
954642e01fSmrg	return error;
964642e01fSmrg    }
974642e01fSmrg
984642e01fSmrg    pc += __GLX_SINGLE_HDR_SIZE;
994642e01fSmrg    __GLX_SWAP_INT(pc+0);
1004642e01fSmrg    size = *(GLsizei *)(pc+0);
1014642e01fSmrg    if (cx->selectBufSize < size) {
1026747b715Smrg	cx->selectBuf = (GLuint *) realloc(cx->selectBuf,
1034642e01fSmrg						(size_t) size
1044642e01fSmrg						* __GLX_SIZE_CARD32);
1054642e01fSmrg	if (!cx->selectBuf) {
1064642e01fSmrg	    cl->client->errorValue = size;
1074642e01fSmrg	    return BadAlloc;
1084642e01fSmrg	}
1094642e01fSmrg	cx->selectBufSize = size;
1104642e01fSmrg    }
1114642e01fSmrg    CALL_SelectBuffer( GET_DISPATCH(), (size, cx->selectBuf) );
1124642e01fSmrg    __GLX_NOTE_UNFLUSHED_CMDS(cx);
1134642e01fSmrg    return Success;
1144642e01fSmrg}
1154642e01fSmrg
1164642e01fSmrgint __glXDispSwap_RenderMode(__GLXclientState *cl, GLbyte *pc)
1174642e01fSmrg{
1180b0d8713Smrg    ClientPtr client = cl->client;
1194642e01fSmrg    __GLXcontext *cx;
1204642e01fSmrg    xGLXRenderModeReply reply;
1214642e01fSmrg    GLint nitems=0, retBytes=0, retval, newModeCheck;
1224642e01fSmrg    GLubyte *retBuffer = NULL;
1234642e01fSmrg    GLenum newMode;
1244642e01fSmrg    __GLX_DECLARE_SWAP_VARIABLES;
1254642e01fSmrg    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
1264642e01fSmrg    int error;
1274642e01fSmrg
1280b0d8713Smrg    REQUEST_FIXED_SIZE(xGLXSingleReq, 4);
1290b0d8713Smrg
1304642e01fSmrg    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
1314642e01fSmrg    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
1324642e01fSmrg    if (!cx) {
1334642e01fSmrg	return error;
1344642e01fSmrg    }
1354642e01fSmrg
1364642e01fSmrg    pc += __GLX_SINGLE_HDR_SIZE;
1374642e01fSmrg    __GLX_SWAP_INT(pc);
1384642e01fSmrg    newMode = *(GLenum*) pc;
1394642e01fSmrg    retval = CALL_RenderMode( GET_DISPATCH(), (newMode) );
1404642e01fSmrg
1414642e01fSmrg    /* Check that render mode worked */
1424642e01fSmrg    CALL_GetIntegerv( GET_DISPATCH(), (GL_RENDER_MODE, &newModeCheck) );
1434642e01fSmrg    if (newModeCheck != newMode) {
1444642e01fSmrg	/* Render mode change failed.  Bail */
1454642e01fSmrg	newMode = newModeCheck;
1464642e01fSmrg	goto noChangeAllowed;
1474642e01fSmrg    }
1484642e01fSmrg
1494642e01fSmrg    /*
1504642e01fSmrg    ** Render mode might have still failed if we get here.  But in this
1514642e01fSmrg    ** case we can't really tell, nor does it matter.  If it did fail, it
1524642e01fSmrg    ** will return 0, and thus we won't send any data across the wire.
1534642e01fSmrg    */
1544642e01fSmrg
1554642e01fSmrg    switch (cx->renderMode) {
1564642e01fSmrg      case GL_RENDER:
1574642e01fSmrg	cx->renderMode = newMode;
1584642e01fSmrg	break;
1594642e01fSmrg      case GL_FEEDBACK:
1604642e01fSmrg	if (retval < 0) {
1614642e01fSmrg	    /* Overflow happened. Copy the entire buffer */
1624642e01fSmrg	    nitems = cx->feedbackBufSize;
1634642e01fSmrg	} else {
1644642e01fSmrg	    nitems = retval;
1654642e01fSmrg	}
1664642e01fSmrg	retBytes = nitems * __GLX_SIZE_FLOAT32;
1674642e01fSmrg	retBuffer = (GLubyte*) cx->feedbackBuf;
1684642e01fSmrg	__GLX_SWAP_FLOAT_ARRAY((GLbyte *)retBuffer, nitems);
1694642e01fSmrg	cx->renderMode = newMode;
1704642e01fSmrg	break;
1714642e01fSmrg      case GL_SELECT:
1724642e01fSmrg	if (retval < 0) {
1734642e01fSmrg	    /* Overflow happened.  Copy the entire buffer */
1744642e01fSmrg	    nitems = cx->selectBufSize;
1754642e01fSmrg	} else {
1764642e01fSmrg	    GLuint *bp = cx->selectBuf;
1774642e01fSmrg	    GLint i;
1784642e01fSmrg
1794642e01fSmrg	    /*
1804642e01fSmrg	    ** Figure out how many bytes of data need to be sent.  Parse
1814642e01fSmrg	    ** the selection buffer to determine this fact as the
1824642e01fSmrg	    ** return value is the number of hits, not the number of
1834642e01fSmrg	    ** items in the buffer.
1844642e01fSmrg	    */
1854642e01fSmrg	    nitems = 0;
1864642e01fSmrg	    i = retval;
1874642e01fSmrg	    while (--i >= 0) {
1884642e01fSmrg		GLuint n;
1894642e01fSmrg
1904642e01fSmrg		/* Parse select data for this hit */
1914642e01fSmrg		n = *bp;
1924642e01fSmrg		bp += 3 + n;
1934642e01fSmrg	    }
1944642e01fSmrg	    nitems = bp - cx->selectBuf;
1954642e01fSmrg	}
1964642e01fSmrg	retBytes = nitems * __GLX_SIZE_CARD32;
1974642e01fSmrg	retBuffer = (GLubyte*) cx->selectBuf;
1984642e01fSmrg	__GLX_SWAP_INT_ARRAY((GLbyte *)retBuffer, nitems);
1994642e01fSmrg	cx->renderMode = newMode;
2004642e01fSmrg	break;
2014642e01fSmrg    }
2024642e01fSmrg
2034642e01fSmrg    /*
2044642e01fSmrg    ** First reply is the number of elements returned in the feedback or
2054642e01fSmrg    ** selection array, as per the API for glRenderMode itself.
2064642e01fSmrg    */
2074642e01fSmrg  noChangeAllowed:;
2084642e01fSmrg    reply.length = nitems;
2094642e01fSmrg    reply.type = X_Reply;
2104642e01fSmrg    reply.sequenceNumber = client->sequence;
2114642e01fSmrg    reply.retval = retval;
2124642e01fSmrg    reply.size = nitems;
2134642e01fSmrg    reply.newMode = newMode;
2144642e01fSmrg    __GLX_SWAP_SHORT(&reply.sequenceNumber);
2154642e01fSmrg    __GLX_SWAP_INT(&reply.length);
2164642e01fSmrg    __GLX_SWAP_INT(&reply.retval);
2174642e01fSmrg    __GLX_SWAP_INT(&reply.size);
2184642e01fSmrg    __GLX_SWAP_INT(&reply.newMode);
2194642e01fSmrg    WriteToClient(client, sz_xGLXRenderModeReply, (char *)&reply);
2204642e01fSmrg    if (retBytes) {
2214642e01fSmrg	WriteToClient(client, retBytes, (char *)retBuffer);
2224642e01fSmrg    }
2234642e01fSmrg    return Success;
2244642e01fSmrg}
2254642e01fSmrg
2264642e01fSmrgint __glXDispSwap_Flush(__GLXclientState *cl, GLbyte *pc)
2274642e01fSmrg{
2280b0d8713Smrg	ClientPtr client = cl->client;
2294642e01fSmrg	__GLXcontext *cx;
2304642e01fSmrg	int error;
2314642e01fSmrg	__GLX_DECLARE_SWAP_VARIABLES;
2324642e01fSmrg
2330b0d8713Smrg	REQUEST_SIZE_MATCH(xGLXSingleReq);
2340b0d8713Smrg
2354642e01fSmrg	__GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
2364642e01fSmrg	cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
2374642e01fSmrg	if (!cx) {
2384642e01fSmrg		return error;
2394642e01fSmrg	}
2404642e01fSmrg
2414642e01fSmrg	CALL_Flush( GET_DISPATCH(), () );
2424642e01fSmrg	__GLX_NOTE_FLUSHED_CMDS(cx);
2434642e01fSmrg	return Success;
2444642e01fSmrg}
2454642e01fSmrg
2464642e01fSmrgint __glXDispSwap_Finish(__GLXclientState *cl, GLbyte *pc)
2474642e01fSmrg{
2480b0d8713Smrg    ClientPtr client = cl->client;
2494642e01fSmrg    __GLXcontext *cx;
2504642e01fSmrg    int error;
2514642e01fSmrg    __GLX_DECLARE_SWAP_VARIABLES;
2524642e01fSmrg
2530b0d8713Smrg    REQUEST_SIZE_MATCH(xGLXSingleReq);
2540b0d8713Smrg
2554642e01fSmrg    __GLX_SWAP_INT(&((xGLXSingleReq *)pc)->contextTag);
2564642e01fSmrg    cx = __glXForceCurrent(cl, __GLX_GET_SINGLE_CONTEXT_TAG(pc), &error);
2574642e01fSmrg    if (!cx) {
2584642e01fSmrg	return error;
2594642e01fSmrg    }
2604642e01fSmrg
2614642e01fSmrg    /* Do a local glFinish */
2624642e01fSmrg    CALL_Finish( GET_DISPATCH(), () );
2634642e01fSmrg    __GLX_NOTE_FLUSHED_CMDS(cx);
2644642e01fSmrg
2654642e01fSmrg    /* Send empty reply packet to indicate finish is finished */
2664642e01fSmrg    __GLX_BEGIN_REPLY(0);
2674642e01fSmrg    __GLX_PUT_RETVAL(0);
2684642e01fSmrg    __GLX_SWAP_REPLY_HEADER();
2694642e01fSmrg    __GLX_SEND_HEADER();
2704642e01fSmrg
2714642e01fSmrg    return Success;
2724642e01fSmrg}
2734642e01fSmrg
2744642e01fSmrgint __glXDispSwap_GetString(__GLXclientState *cl, GLbyte *pc)
2754642e01fSmrg{
2764642e01fSmrg    return DoGetString(cl, pc, GL_TRUE);
2774642e01fSmrg}
278