14642e01fSmrg/*
24642e01fSmrg * (C) Copyright IBM Corporation 2005
34642e01fSmrg * All Rights Reserved.
4f7df2e56Smrg *
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, sub license,
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:
11f7df2e56Smrg *
124642e01fSmrg * The above copyright notice and this permission notice (including the next
134642e01fSmrg * paragraph) shall be included in all copies or substantial portions of the
144642e01fSmrg * Software.
15f7df2e56Smrg *
164642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
174642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
184642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
194642e01fSmrg * IBM,
204642e01fSmrg * AND/OR THEIR SUPPLIERS 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
264642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
274642e01fSmrg#include <dix-config.h>
284642e01fSmrg#endif
294642e01fSmrg
304642e01fSmrg#include <string.h>
314642e01fSmrg
324642e01fSmrg#include <X11/Xmd.h>
334642e01fSmrg#include <GL/gl.h>
344642e01fSmrg#include <GL/glxproto.h>
354642e01fSmrg#include <inttypes.h>
364642e01fSmrg#include "indirect_size.h"
374642e01fSmrg#include "indirect_size_get.h"
384642e01fSmrg#include "indirect_dispatch.h"
394642e01fSmrg#include "glxserver.h"
404642e01fSmrg#include "glxbyteorder.h"
414642e01fSmrg#include "singlesize.h"
424642e01fSmrg#include "glxext.h"
434642e01fSmrg#include "indirect_table.h"
444642e01fSmrg#include "indirect_util.h"
454642e01fSmrg
464642e01fSmrg#define __GLX_PAD(a) (((a)+3)&~3)
474642e01fSmrg
484642e01fSmrgGLint
49f7df2e56Smrg__glGetBooleanv_variable_size(GLenum e)
504642e01fSmrg{
51f7df2e56Smrg    if (e == GL_COMPRESSED_TEXTURE_FORMATS) {
52f7df2e56Smrg        GLint temp;
534642e01fSmrg
54f7df2e56Smrg        glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp);
55f7df2e56Smrg        return temp;
564642e01fSmrg    }
574642e01fSmrg    else {
58f7df2e56Smrg        return 0;
594642e01fSmrg    }
604642e01fSmrg}
614642e01fSmrg
624642e01fSmrg/**
634642e01fSmrg * Get a properly aligned buffer to hold reply data.
644642e01fSmrg *
654642e01fSmrg * \warning
664642e01fSmrg * This function assumes that \c local_buffer is already properly aligned.
674642e01fSmrg * It also assumes that \c alignment is a power of two.
684642e01fSmrg */
694642e01fSmrgvoid *
70f7df2e56Smrg__glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size,
71f7df2e56Smrg                     void *local_buffer, size_t local_size, unsigned alignment)
724642e01fSmrg{
73f7df2e56Smrg    void *buffer = local_buffer;
740b0d8713Smrg    const intptr_t mask = alignment - 1;
754642e01fSmrg
76f7df2e56Smrg    if (local_size < required_size) {
770b0d8713Smrg        size_t worst_case_size;
78f7df2e56Smrg        intptr_t temp_buf;
794642e01fSmrg
800b0d8713Smrg        if (required_size < SIZE_MAX - alignment)
810b0d8713Smrg            worst_case_size = required_size + alignment;
820b0d8713Smrg        else
830b0d8713Smrg            return NULL;
840b0d8713Smrg
85f7df2e56Smrg        if (cl->returnBufSize < worst_case_size) {
86f7df2e56Smrg            void *temp = realloc(cl->returnBuf, worst_case_size);
87f7df2e56Smrg
88f7df2e56Smrg            if (temp == NULL) {
89f7df2e56Smrg                return NULL;
90f7df2e56Smrg            }
91f7df2e56Smrg
92f7df2e56Smrg            cl->returnBuf = temp;
93f7df2e56Smrg            cl->returnBufSize = worst_case_size;
94f7df2e56Smrg        }
95f7df2e56Smrg
96f7df2e56Smrg        temp_buf = (intptr_t) cl->returnBuf;
97f7df2e56Smrg        temp_buf = (temp_buf + mask) & ~mask;
98f7df2e56Smrg        buffer = (void *) temp_buf;
994642e01fSmrg    }
1004642e01fSmrg
1014642e01fSmrg    return buffer;
1024642e01fSmrg}
1034642e01fSmrg
1044642e01fSmrg/**
1054642e01fSmrg * Send a GLX reply to the client.
1064642e01fSmrg *
1074642e01fSmrg * Technically speaking, there are several different ways to encode a GLX
1084642e01fSmrg * reply.  The primary difference is whether or not certain fields (e.g.,
1094642e01fSmrg * retval, size, and "pad3") are set.  This function gets around that by
1104642e01fSmrg * always setting all of the fields to "reasonable" values.  This does no
1114642e01fSmrg * harm to clients, but it does make the server-side code much more compact.
1124642e01fSmrg */
1134642e01fSmrgvoid
114f7df2e56Smrg__glXSendReply(ClientPtr client, const void *data, size_t elements,
115f7df2e56Smrg               size_t element_size, GLboolean always_array, CARD32 retval)
1164642e01fSmrg{
1174642e01fSmrg    size_t reply_ints = 0;
1187e31ba66Smrg    xGLXSingleReply reply = { 0, };
1194642e01fSmrg
120f7df2e56Smrg    if (__glXErrorOccured()) {
1214642e01fSmrg        elements = 0;
1224642e01fSmrg    }
123f7df2e56Smrg    else if ((elements > 1) || always_array) {
1246747b715Smrg        reply_ints = bytes_to_int32(elements * element_size);
1254642e01fSmrg    }
1264642e01fSmrg
1277e31ba66Smrg    reply.length = reply_ints;
1287e31ba66Smrg    reply.type = X_Reply;
1297e31ba66Smrg    reply.sequenceNumber = client->sequence;
1307e31ba66Smrg    reply.size = elements;
1317e31ba66Smrg    reply.retval = retval;
1324642e01fSmrg
1334642e01fSmrg    /* It is faster on almost always every architecture to just copy the 8
1344642e01fSmrg     * bytes, even when not necessary, than check to see of the value of
1354642e01fSmrg     * elements requires it.  Copying the data when not needed will do no
1364642e01fSmrg     * harm.
1374642e01fSmrg     */
1384642e01fSmrg
1397e31ba66Smrg    (void) memcpy(&reply.pad3, data, 8);
1407e31ba66Smrg    WriteToClient(client, sz_xGLXSingleReply, &reply);
1414642e01fSmrg
142f7df2e56Smrg    if (reply_ints != 0) {
143f7df2e56Smrg        WriteToClient(client, reply_ints * 4, data);
1444642e01fSmrg    }
1454642e01fSmrg}
1464642e01fSmrg
1474642e01fSmrg/**
1484642e01fSmrg * Send a GLX reply to the client.
1494642e01fSmrg *
1504642e01fSmrg * Technically speaking, there are several different ways to encode a GLX
1514642e01fSmrg * reply.  The primary difference is whether or not certain fields (e.g.,
1524642e01fSmrg * retval, size, and "pad3") are set.  This function gets around that by
1534642e01fSmrg * always setting all of the fields to "reasonable" values.  This does no
1544642e01fSmrg * harm to clients, but it does make the server-side code much more compact.
1554642e01fSmrg *
1564642e01fSmrg * \warning
1574642e01fSmrg * This function assumes that values stored in \c data will be byte-swapped
1584642e01fSmrg * by the caller if necessary.
1594642e01fSmrg */
1604642e01fSmrgvoid
161f7df2e56Smrg__glXSendReplySwap(ClientPtr client, const void *data, size_t elements,
162f7df2e56Smrg                   size_t element_size, GLboolean always_array, CARD32 retval)
1634642e01fSmrg{
1644642e01fSmrg    size_t reply_ints = 0;
1657e31ba66Smrg    xGLXSingleReply reply = { 0, };
1664642e01fSmrg
167f7df2e56Smrg    if (__glXErrorOccured()) {
1684642e01fSmrg        elements = 0;
1694642e01fSmrg    }
170f7df2e56Smrg    else if ((elements > 1) || always_array) {
1716747b715Smrg        reply_ints = bytes_to_int32(elements * element_size);
1724642e01fSmrg    }
1734642e01fSmrg
1747e31ba66Smrg    reply.length = bswap_32(reply_ints);
1757e31ba66Smrg    reply.type = X_Reply;
1767e31ba66Smrg    reply.sequenceNumber = bswap_16(client->sequence);
1777e31ba66Smrg    reply.size = bswap_32(elements);
1787e31ba66Smrg    reply.retval = bswap_32(retval);
1794642e01fSmrg
1804642e01fSmrg    /* It is faster on almost always every architecture to just copy the 8
1814642e01fSmrg     * bytes, even when not necessary, than check to see of the value of
1824642e01fSmrg     * elements requires it.  Copying the data when not needed will do no
1834642e01fSmrg     * harm.
1844642e01fSmrg     */
1854642e01fSmrg
1867e31ba66Smrg    (void) memcpy(&reply.pad3, data, 8);
1877e31ba66Smrg    WriteToClient(client, sz_xGLXSingleReply, &reply);
1884642e01fSmrg
189f7df2e56Smrg    if (reply_ints != 0) {
190f7df2e56Smrg        WriteToClient(client, reply_ints * 4, data);
1914642e01fSmrg    }
1924642e01fSmrg}
1934642e01fSmrg
1944642e01fSmrgstatic int
195f7df2e56Smrgget_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode)
1964642e01fSmrg{
1974642e01fSmrg    int remaining_bits;
1984642e01fSmrg    int next_remain;
199f7df2e56Smrg    const int_fast16_t *const tree = dispatch_info->dispatch_tree;
2004642e01fSmrg    int_fast16_t index;
2014642e01fSmrg
2024642e01fSmrg    remaining_bits = dispatch_info->bits;
2034642e01fSmrg    if (opcode >= (1U << remaining_bits)) {
204f7df2e56Smrg        return -1;
2054642e01fSmrg    }
2064642e01fSmrg
207f7df2e56Smrg    index = 0;
208f7df2e56Smrg    for ( /* empty */ ; remaining_bits > 0; remaining_bits = next_remain) {
209f7df2e56Smrg        unsigned mask;
210f7df2e56Smrg        unsigned child_index;
211f7df2e56Smrg
212f7df2e56Smrg        /* Calculate the slice of bits used by this node.
213f7df2e56Smrg         *
214f7df2e56Smrg         * If remaining_bits = 8 and tree[index] = 3, the mask of just the
215f7df2e56Smrg         * remaining bits is 0x00ff and the mask for the remaining bits after
216f7df2e56Smrg         * this node is 0x001f.  By taking 0x00ff & ~0x001f, we get 0x00e0.
217f7df2e56Smrg         * This masks the 3 bits that we would want for this node.
218f7df2e56Smrg         */
219f7df2e56Smrg
220f7df2e56Smrg        next_remain = remaining_bits - tree[index];
221f7df2e56Smrg        mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1);
222f7df2e56Smrg
223f7df2e56Smrg        /* Using the mask, calculate the index of the opcode in the node.
224f7df2e56Smrg         * With that index, fetch the index of the next node.
225f7df2e56Smrg         */
226f7df2e56Smrg
227f7df2e56Smrg        child_index = (opcode & mask) >> next_remain;
228f7df2e56Smrg        index = tree[index + 1 + child_index];
229f7df2e56Smrg
2305a112b11Smrg        /* If the next node is an empty leaf, the opcode is for a non-existent
231f7df2e56Smrg         * function.  We're done.
232f7df2e56Smrg         *
233f7df2e56Smrg         * If the next node is a non-empty leaf, look up the function pointer
234f7df2e56Smrg         * and return it.
235f7df2e56Smrg         */
236f7df2e56Smrg
237f7df2e56Smrg        if (index == EMPTY_LEAF) {
238f7df2e56Smrg            return -1;
239f7df2e56Smrg        }
240f7df2e56Smrg        else if (IS_LEAF_INDEX(index)) {
241f7df2e56Smrg            unsigned func_index;
242f7df2e56Smrg
243f7df2e56Smrg            /* The value stored in the tree for a leaf node is the base of
244f7df2e56Smrg             * the function pointers for that leaf node.  The offset for the
245f7df2e56Smrg             * function for a particular opcode is the remaining bits in the
246f7df2e56Smrg             * opcode.
247f7df2e56Smrg             */
248f7df2e56Smrg
249f7df2e56Smrg            func_index = -index;
250f7df2e56Smrg            func_index += opcode & ((1 << next_remain) - 1);
251f7df2e56Smrg            return func_index;
252f7df2e56Smrg        }
2534642e01fSmrg    }
2544642e01fSmrg
2554642e01fSmrg    /* We should *never* get here!!!
2564642e01fSmrg     */
2574642e01fSmrg    return -1;
2584642e01fSmrg}
2594642e01fSmrg
2604642e01fSmrgvoid *
2614642e01fSmrg__glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
262f7df2e56Smrg                               int opcode, int swapped_version)
2634642e01fSmrg{
2644642e01fSmrg    const int func_index = get_decode_index(dispatch_info, opcode);
2654642e01fSmrg
266f7df2e56Smrg    return (func_index < 0)
267f7df2e56Smrg        ? NULL
268f7df2e56Smrg        : (void *) dispatch_info->
269f7df2e56Smrg        dispatch_functions[func_index][swapped_version];
2704642e01fSmrg}
2714642e01fSmrg
2724642e01fSmrgint
2734642e01fSmrg__glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
274f7df2e56Smrg                         int opcode, __GLXrenderSizeData * data)
2754642e01fSmrg{
2764642e01fSmrg    if (dispatch_info->size_table != NULL) {
277f7df2e56Smrg        const int func_index = get_decode_index(dispatch_info, opcode);
2784642e01fSmrg
279f7df2e56Smrg        if ((func_index >= 0)
280f7df2e56Smrg            && (dispatch_info->size_table[func_index][0] != 0)) {
281f7df2e56Smrg            const int var_offset = dispatch_info->size_table[func_index][1];
2824642e01fSmrg
283f7df2e56Smrg            data->bytes = dispatch_info->size_table[func_index][0];
284f7df2e56Smrg            data->varsize = (var_offset != ~0)
285f7df2e56Smrg                ? dispatch_info->size_func_table[var_offset]
286f7df2e56Smrg                : NULL;
2874642e01fSmrg
288f7df2e56Smrg            return 0;
289f7df2e56Smrg        }
2904642e01fSmrg    }
2914642e01fSmrg
2924642e01fSmrg    return -1;
2934642e01fSmrg}
294