aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glx/indirect_util.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2012-03-26 14:23:28 +0200
committermarha <marha@users.sourceforge.net>2012-03-26 14:23:28 +0200
commit76bcc36ed305418a3ddc5752d287ede894243e1b (patch)
treebacb320c825768471ce56f058f17ce863d592376 /xorg-server/glx/indirect_util.c
parent7d894e32566b710952c44cbc71939ad1d9e2fa8d (diff)
parent0f834b91a4768673833ab4917e87d86c237bb1a6 (diff)
downloadvcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.gz
vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.bz2
vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.zip
Merge remote-tracking branch 'origin/released'
Conflicts: pixman/pixman/pixman-mmx.c xorg-server/Xext/shm.c xorg-server/Xext/syncsrv.h xorg-server/Xext/xvmain.c xorg-server/Xi/exevents.c xorg-server/Xi/opendev.c xorg-server/composite/compalloc.c xorg-server/composite/compoverlay.c xorg-server/dix/colormap.c xorg-server/dix/devices.c xorg-server/dix/dispatch.c xorg-server/dix/dixfonts.c xorg-server/dix/eventconvert.c xorg-server/dix/events.c xorg-server/dix/gc.c xorg-server/dix/getevents.c xorg-server/dix/main.c xorg-server/dix/privates.c xorg-server/dix/registry.c xorg-server/dix/resource.c xorg-server/exa/exa_accel.c xorg-server/exa/exa_migration_classic.c xorg-server/exa/exa_unaccel.c xorg-server/fb/fb.h xorg-server/fb/fbcopy.c xorg-server/fb/fbpixmap.c xorg-server/glx/dispatch.h xorg-server/glx/glapi.h xorg-server/glx/glapi_gentable.c xorg-server/glx/glapitable.h xorg-server/glx/glprocs.h xorg-server/glx/glxcmds.c xorg-server/glx/glxcmdsswap.c xorg-server/glx/glxdricommon.c xorg-server/glx/glxdriswrast.c xorg-server/glx/glxext.c xorg-server/glx/indirect_dispatch.c xorg-server/glx/indirect_dispatch.h xorg-server/glx/indirect_dispatch_swap.c xorg-server/glx/indirect_size.h xorg-server/glx/indirect_size_get.h xorg-server/glx/indirect_table.c xorg-server/glx/indirect_util.c xorg-server/glx/rensize.c xorg-server/glx/single2swap.c xorg-server/glx/singlepix.c xorg-server/glx/singlepixswap.c xorg-server/glx/singlesize.c xorg-server/hw/dmx/dmxinit.c xorg-server/hw/kdrive/ephyr/ephyr.c xorg-server/hw/kdrive/ephyr/hostx.c xorg-server/hw/kdrive/ephyr/hostx.h xorg-server/hw/kdrive/src/kinput.c xorg-server/hw/xfree86/common/compiler.h xorg-server/hw/xwin/InitInput.c xorg-server/hw/xwin/InitOutput.c xorg-server/hw/xwin/ddraw.h xorg-server/hw/xwin/glx/glwrap.c xorg-server/hw/xwin/glx/indirect.c xorg-server/hw/xwin/glx/wgl_ext_api.h xorg-server/hw/xwin/glx/winpriv.c xorg-server/hw/xwin/win.h xorg-server/hw/xwin/winallpriv.c xorg-server/hw/xwin/winauth.c xorg-server/hw/xwin/winclipboard.h xorg-server/hw/xwin/winclipboardinit.c xorg-server/hw/xwin/winclipboardthread.c xorg-server/hw/xwin/winclipboardunicode.c xorg-server/hw/xwin/winclipboardwndproc.c xorg-server/hw/xwin/winclipboardwrappers.c xorg-server/hw/xwin/winclipboardxevents.c xorg-server/hw/xwin/wincmap.c xorg-server/hw/xwin/winconfig.c xorg-server/hw/xwin/wincreatewnd.c xorg-server/hw/xwin/wincursor.c xorg-server/hw/xwin/windialogs.c xorg-server/hw/xwin/winengine.c xorg-server/hw/xwin/winerror.c xorg-server/hw/xwin/wingc.c xorg-server/hw/xwin/wingetsp.c xorg-server/hw/xwin/winkeybd.c xorg-server/hw/xwin/winkeybd.h xorg-server/hw/xwin/winlayouts.h xorg-server/hw/xwin/winmisc.c xorg-server/hw/xwin/winmonitors.c xorg-server/hw/xwin/winmouse.c xorg-server/hw/xwin/winmsg.c xorg-server/hw/xwin/winmsg.h xorg-server/hw/xwin/winmultiwindowclass.c xorg-server/hw/xwin/winmultiwindowicons.c xorg-server/hw/xwin/winmultiwindowshape.c xorg-server/hw/xwin/winmultiwindowwindow.c xorg-server/hw/xwin/winmultiwindowwm.c xorg-server/hw/xwin/winmultiwindowwndproc.c xorg-server/hw/xwin/winnativegdi.c xorg-server/hw/xwin/winpfbdd.c xorg-server/hw/xwin/winpixmap.c xorg-server/hw/xwin/winpolyline.c xorg-server/hw/xwin/winprefs.c xorg-server/hw/xwin/winprocarg.c xorg-server/hw/xwin/winregistry.c xorg-server/hw/xwin/winscrinit.c xorg-server/hw/xwin/winsetsp.c xorg-server/hw/xwin/winshaddd.c xorg-server/hw/xwin/winshadddnl.c xorg-server/hw/xwin/winshadgdi.c xorg-server/hw/xwin/wintrayicon.c xorg-server/hw/xwin/winwin32rootless.c xorg-server/hw/xwin/winwin32rootlesswindow.c xorg-server/hw/xwin/winwin32rootlesswndproc.c xorg-server/hw/xwin/winwindow.c xorg-server/hw/xwin/winwindow.h xorg-server/hw/xwin/winwindowswm.c xorg-server/hw/xwin/winwndproc.c xorg-server/include/callback.h xorg-server/include/dixstruct.h xorg-server/include/misc.h xorg-server/include/os.h xorg-server/include/scrnintstr.h xorg-server/mi/micmap.c xorg-server/mi/miinitext.c xorg-server/mi/mioverlay.c xorg-server/mi/misprite.c xorg-server/mi/mivaltree.c xorg-server/mi/miwindow.c xorg-server/miext/damage/damage.c xorg-server/miext/rootless/rootlessGC.c xorg-server/miext/rootless/rootlessWindow.c xorg-server/os/WaitFor.c xorg-server/os/access.c xorg-server/os/connection.c xorg-server/os/io.c xorg-server/os/log.c xorg-server/os/osinit.c xorg-server/os/utils.c xorg-server/os/xdmcp.c xorg-server/os/xprintf.c xorg-server/os/xstrans.c xorg-server/render/mipict.c xorg-server/xkb/xkbActions.c xorg-server/xkb/xkbInit.c xorg-server/xkeyboard-config/compat/default.in
Diffstat (limited to 'xorg-server/glx/indirect_util.c')
-rw-r--r--xorg-server/glx/indirect_util.c611
1 files changed, 297 insertions, 314 deletions
diff --git a/xorg-server/glx/indirect_util.c b/xorg-server/glx/indirect_util.c
index f71fe6dd2..66604617e 100644
--- a/xorg-server/glx/indirect_util.c
+++ b/xorg-server/glx/indirect_util.c
@@ -1,314 +1,297 @@
-/*
- * (C) Copyright IBM Corporation 2005
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * IBM,
- * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#else
-
-#include "glheader.h"
-
-#endif
-
-#include <string.h>
-
-#include <X11/Xmd.h>
-#include <GL/gl.h>
-#include <GL/glxproto.h>
-#include <inttypes.h>
-#include "indirect_size.h"
-#include "indirect_size_get.h"
-#include "indirect_dispatch.h"
-#include "glxserver.h"
-#include "glxbyteorder.h"
-#include "singlesize.h"
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "glxext.h"
-#include "indirect_table.h"
-#include "indirect_util.h"
-
-
-#define __GLX_PAD(a) (((a)+3)&~3)
-
-extern xGLXSingleReply __glXReply;
-
-
-GLint
-__glGetBooleanv_variable_size( GLenum e )
-{
- if ( e == GL_COMPRESSED_TEXTURE_FORMATS ) {
- GLint temp;
-
- CALL_GetIntegerv( GET_DISPATCH(),
- (GL_NUM_COMPRESSED_TEXTURE_FORMATS, & temp) );
- return temp;
- }
- else {
- return 0;
- }
-}
-
-
-/**
- * Get a properly aligned buffer to hold reply data.
- *
- * \warning
- * This function assumes that \c local_buffer is already properly aligned.
- * It also assumes that \c alignment is a power of two.
- */
-void *
-__glXGetAnswerBuffer( __GLXclientState * cl, size_t required_size,
- void * local_buffer, size_t local_size, unsigned alignment )
-{
- void * buffer = local_buffer;
- const unsigned mask = alignment - 1;
-
- if ( local_size < required_size ) {
- const size_t worst_case_size = required_size + alignment;
- intptr_t temp_buf;
-
- if ( cl->returnBufSize < worst_case_size ) {
- void * temp = realloc( cl->returnBuf, worst_case_size );
-
- if ( temp == NULL ) {
- return NULL;
- }
-
- cl->returnBuf = temp;
- cl->returnBufSize = worst_case_size;
- }
-
- temp_buf = (intptr_t) cl->returnBuf;
- temp_buf = (temp_buf + mask) & ~mask;
- buffer = (void *) temp_buf;
- }
-
- return buffer;
-}
-
-
-/**
- * Send a GLX reply to the client.
- *
- * Technically speaking, there are several different ways to encode a GLX
- * reply. The primary difference is whether or not certain fields (e.g.,
- * retval, size, and "pad3") are set. This function gets around that by
- * always setting all of the fields to "reasonable" values. This does no
- * harm to clients, but it does make the server-side code much more compact.
- */
-void
-__glXSendReply( ClientPtr client, const void * data, size_t elements,
- size_t element_size, GLboolean always_array, CARD32 retval )
-{
- size_t reply_ints = 0;
-
- if ( __glXErrorOccured() ) {
- elements = 0;
- }
- else if ( (elements > 1) || always_array ) {
- reply_ints = bytes_to_int32(elements * element_size);
- }
-
- __glXReply.length = reply_ints;
- __glXReply.type = X_Reply;
- __glXReply.sequenceNumber = client->sequence;
- __glXReply.size = elements;
- __glXReply.retval = retval;
-
-
- /* It is faster on almost always every architecture to just copy the 8
- * bytes, even when not necessary, than check to see of the value of
- * elements requires it. Copying the data when not needed will do no
- * harm.
- */
-
- (void) memcpy( & __glXReply.pad3, data, 8 );
- WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
-
- if ( reply_ints != 0 ) {
- WriteToClient( client, reply_ints * 4, (char *) data );
- }
-}
-
-
-/**
- * Send a GLX reply to the client.
- *
- * Technically speaking, there are several different ways to encode a GLX
- * reply. The primary difference is whether or not certain fields (e.g.,
- * retval, size, and "pad3") are set. This function gets around that by
- * always setting all of the fields to "reasonable" values. This does no
- * harm to clients, but it does make the server-side code much more compact.
- *
- * \warning
- * This function assumes that values stored in \c data will be byte-swapped
- * by the caller if necessary.
- */
-void
-__glXSendReplySwap( ClientPtr client, const void * data, size_t elements,
- size_t element_size, GLboolean always_array, CARD32 retval )
-{
- size_t reply_ints = 0;
-
- if ( __glXErrorOccured() ) {
- elements = 0;
- }
- else if ( (elements > 1) || always_array ) {
- reply_ints = bytes_to_int32(elements * element_size);
- }
-
- __glXReply.length = bswap_32( reply_ints );
- __glXReply.type = X_Reply;
- __glXReply.sequenceNumber = bswap_16( client->sequence );
- __glXReply.size = bswap_32( elements );
- __glXReply.retval = bswap_32( retval );
-
-
- /* It is faster on almost always every architecture to just copy the 8
- * bytes, even when not necessary, than check to see of the value of
- * elements requires it. Copying the data when not needed will do no
- * harm.
- */
-
- (void) memcpy( & __glXReply.pad3, data, 8 );
- WriteToClient( client, sz_xGLXSingleReply, (char *) & __glXReply );
-
- if ( reply_ints != 0 ) {
- WriteToClient( client, reply_ints * 4, (char *) data );
- }
-}
-
-
-static int
-get_decode_index(const struct __glXDispatchInfo *dispatch_info,
- unsigned opcode)
-{
- int remaining_bits;
- int next_remain;
- const int_fast16_t * const tree = dispatch_info->dispatch_tree;
- int_fast16_t index;
-
-
- remaining_bits = dispatch_info->bits;
- if (opcode >= (1U << remaining_bits)) {
- return -1;
- }
-
- index = 0;
- for (/* empty */; remaining_bits > 0; remaining_bits = next_remain) {
- unsigned mask;
- unsigned child_index;
-
-
- /* Calculate the slice of bits used by this node.
- *
- * If remaining_bits = 8 and tree[index] = 3, the mask of just the
- * remaining bits is 0x00ff and the mask for the remaining bits after
- * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0.
- * This masks the 3 bits that we would want for this node.
- */
-
- next_remain = remaining_bits - tree[index];
- mask = ((1 << remaining_bits) - 1) &
- ~((1 << next_remain) - 1);
-
-
- /* Using the mask, calculate the index of the opcode in the node.
- * With that index, fetch the index of the next node.
- */
-
- child_index = (opcode & mask) >> next_remain;
- index = tree[index + 1 + child_index];
-
-
- /* If the next node is an empty leaf, the opcode is for a non-existant
- * function. We're done.
- *
- * If the next node is a non-empty leaf, look up the function pointer
- * and return it.
- */
-
- if (index == EMPTY_LEAF) {
- return -1;
- }
- else if (IS_LEAF_INDEX(index)) {
- unsigned func_index;
-
-
- /* The value stored in the tree for a leaf node is the base of
- * the function pointers for that leaf node. The offset for the
- * function for a particular opcode is the remaining bits in the
- * opcode.
- */
-
- func_index = -index;
- func_index += opcode & ((1 << next_remain) - 1);
- return func_index;
- }
- }
-
- /* We should *never* get here!!!
- */
- return -1;
-}
-
-
-void *
-__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
- int opcode, int swapped_version)
-{
- const int func_index = get_decode_index(dispatch_info, opcode);
-
- return (func_index < 0)
- ? NULL
- : (void *) dispatch_info->dispatch_functions[func_index][swapped_version];
-}
-
-
-int
-__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
- int opcode, __GLXrenderSizeData *data)
-{
- if (dispatch_info->size_table != NULL) {
- const int func_index = get_decode_index(dispatch_info, opcode);
-
- if ((func_index >= 0)
- && (dispatch_info->size_table[func_index][0] != 0)) {
- const int var_offset =
- dispatch_info->size_table[func_index][1];
-
- data->bytes = dispatch_info->size_table[func_index][0];
- data->varsize = (var_offset != ~0)
- ? dispatch_info->size_func_table[var_offset]
- : NULL;
-
- return 0;
- }
- }
-
- return -1;
-}
+/*
+ * (C) Copyright IBM Corporation 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * IBM,
+ * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#else
+
+#include "glheader.h"
+
+#endif
+
+#include <string.h>
+
+#include <X11/Xmd.h>
+#include <GL/gl.h>
+#include <GL/glxproto.h>
+#include <inttypes.h>
+#include "indirect_size.h"
+#include "indirect_size_get.h"
+#include "indirect_dispatch.h"
+#include "glxserver.h"
+#include "glxbyteorder.h"
+#include "singlesize.h"
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "glxext.h"
+#include "indirect_table.h"
+#include "indirect_util.h"
+
+#define __GLX_PAD(a) (((a)+3)&~3)
+
+extern xGLXSingleReply __glXReply;
+
+GLint
+__glGetBooleanv_variable_size(GLenum e)
+{
+ if (e == GL_COMPRESSED_TEXTURE_FORMATS) {
+ GLint temp;
+
+ CALL_GetIntegerv(GET_DISPATCH(),
+ (GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp));
+ return temp;
+ }
+ else {
+ return 0;
+ }
+}
+
+/**
+ * Get a properly aligned buffer to hold reply data.
+ *
+ * \warning
+ * This function assumes that \c local_buffer is already properly aligned.
+ * It also assumes that \c alignment is a power of two.
+ */
+void *
+__glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size,
+ void *local_buffer, size_t local_size, unsigned alignment)
+{
+ void *buffer = local_buffer;
+ const unsigned mask = alignment - 1;
+
+ if (local_size < required_size) {
+ const size_t worst_case_size = required_size + alignment;
+ intptr_t temp_buf;
+
+ if (cl->returnBufSize < worst_case_size) {
+ void *temp = realloc(cl->returnBuf, worst_case_size);
+
+ if (temp == NULL) {
+ return NULL;
+ }
+
+ cl->returnBuf = temp;
+ cl->returnBufSize = worst_case_size;
+ }
+
+ temp_buf = (intptr_t) cl->returnBuf;
+ temp_buf = (temp_buf + mask) & ~mask;
+ buffer = (void *) temp_buf;
+ }
+
+ return buffer;
+}
+
+/**
+ * Send a GLX reply to the client.
+ *
+ * Technically speaking, there are several different ways to encode a GLX
+ * reply. The primary difference is whether or not certain fields (e.g.,
+ * retval, size, and "pad3") are set. This function gets around that by
+ * always setting all of the fields to "reasonable" values. This does no
+ * harm to clients, but it does make the server-side code much more compact.
+ */
+void
+__glXSendReply(ClientPtr client, const void *data, size_t elements,
+ size_t element_size, GLboolean always_array, CARD32 retval)
+{
+ size_t reply_ints = 0;
+
+ if (__glXErrorOccured()) {
+ elements = 0;
+ }
+ else if ((elements > 1) || always_array) {
+ reply_ints = bytes_to_int32(elements * element_size);
+ }
+
+ __glXReply.length = reply_ints;
+ __glXReply.type = X_Reply;
+ __glXReply.sequenceNumber = client->sequence;
+ __glXReply.size = elements;
+ __glXReply.retval = retval;
+
+ /* It is faster on almost always every architecture to just copy the 8
+ * bytes, even when not necessary, than check to see of the value of
+ * elements requires it. Copying the data when not needed will do no
+ * harm.
+ */
+
+ (void) memcpy(&__glXReply.pad3, data, 8);
+ WriteToClient(client, sz_xGLXSingleReply, (char *) &__glXReply);
+
+ if (reply_ints != 0) {
+ WriteToClient(client, reply_ints * 4, (char *) data);
+ }
+}
+
+/**
+ * Send a GLX reply to the client.
+ *
+ * Technically speaking, there are several different ways to encode a GLX
+ * reply. The primary difference is whether or not certain fields (e.g.,
+ * retval, size, and "pad3") are set. This function gets around that by
+ * always setting all of the fields to "reasonable" values. This does no
+ * harm to clients, but it does make the server-side code much more compact.
+ *
+ * \warning
+ * This function assumes that values stored in \c data will be byte-swapped
+ * by the caller if necessary.
+ */
+void
+__glXSendReplySwap(ClientPtr client, const void *data, size_t elements,
+ size_t element_size, GLboolean always_array, CARD32 retval)
+{
+ size_t reply_ints = 0;
+
+ if (__glXErrorOccured()) {
+ elements = 0;
+ }
+ else if ((elements > 1) || always_array) {
+ reply_ints = bytes_to_int32(elements * element_size);
+ }
+
+ __glXReply.length = bswap_32(reply_ints);
+ __glXReply.type = X_Reply;
+ __glXReply.sequenceNumber = bswap_16(client->sequence);
+ __glXReply.size = bswap_32(elements);
+ __glXReply.retval = bswap_32(retval);
+
+ /* It is faster on almost always every architecture to just copy the 8
+ * bytes, even when not necessary, than check to see of the value of
+ * elements requires it. Copying the data when not needed will do no
+ * harm.
+ */
+
+ (void) memcpy(&__glXReply.pad3, data, 8);
+ WriteToClient(client, sz_xGLXSingleReply, (char *) &__glXReply);
+
+ if (reply_ints != 0) {
+ WriteToClient(client, reply_ints * 4, (char *) data);
+ }
+}
+
+static int
+get_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode)
+{
+ int remaining_bits;
+ int next_remain;
+ const int_fast16_t *const tree = dispatch_info->dispatch_tree;
+ int_fast16_t index;
+
+ remaining_bits = dispatch_info->bits;
+ if (opcode >= (1U << remaining_bits)) {
+ return -1;
+ }
+
+ index = 0;
+ for ( /* empty */ ; remaining_bits > 0; remaining_bits = next_remain) {
+ unsigned mask;
+ unsigned child_index;
+
+ /* Calculate the slice of bits used by this node.
+ *
+ * If remaining_bits = 8 and tree[index] = 3, the mask of just the
+ * remaining bits is 0x00ff and the mask for the remaining bits after
+ * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0.
+ * This masks the 3 bits that we would want for this node.
+ */
+
+ next_remain = remaining_bits - tree[index];
+ mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1);
+
+ /* Using the mask, calculate the index of the opcode in the node.
+ * With that index, fetch the index of the next node.
+ */
+
+ child_index = (opcode & mask) >> next_remain;
+ index = tree[index + 1 + child_index];
+
+ /* If the next node is an empty leaf, the opcode is for a non-existant
+ * function. We're done.
+ *
+ * If the next node is a non-empty leaf, look up the function pointer
+ * and return it.
+ */
+
+ if (index == EMPTY_LEAF) {
+ return -1;
+ }
+ else if (IS_LEAF_INDEX(index)) {
+ unsigned func_index;
+
+ /* The value stored in the tree for a leaf node is the base of
+ * the function pointers for that leaf node. The offset for the
+ * function for a particular opcode is the remaining bits in the
+ * opcode.
+ */
+
+ func_index = -index;
+ func_index += opcode & ((1 << next_remain) - 1);
+ return func_index;
+ }
+ }
+
+ /* We should *never* get here!!!
+ */
+ return -1;
+}
+
+void *
+__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
+ int opcode, int swapped_version)
+{
+ const int func_index = get_decode_index(dispatch_info, opcode);
+
+ return (func_index < 0)
+ ? NULL
+ : (void *) dispatch_info->
+ dispatch_functions[func_index][swapped_version];
+}
+
+int
+__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
+ int opcode, __GLXrenderSizeData * data)
+{
+ if (dispatch_info->size_table != NULL) {
+ const int func_index = get_decode_index(dispatch_info, opcode);
+
+ if ((func_index >= 0)
+ && (dispatch_info->size_table[func_index][0] != 0)) {
+ const int var_offset = dispatch_info->size_table[func_index][1];
+
+ data->bytes = dispatch_info->size_table[func_index][0];
+ data->varsize = (var_offset != ~0)
+ ? dispatch_info->size_func_table[var_offset]
+ : NULL;
+
+ return 0;
+ }
+ }
+
+ return -1;
+}