indirect_util.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * (C) Copyright IBM Corporation 2005
  3. * 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, sub license,
  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 and this permission notice (including the next
  13. * paragraph) shall be included in all copies or substantial portions of the
  14. * Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  19. * IBM,
  20. * AND/OR THEIR SUPPLIERS 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. #ifdef HAVE_DIX_CONFIG_H
  26. #include <dix-config.h>
  27. #endif
  28. #include <string.h>
  29. #include <X11/Xmd.h>
  30. #include <GL/gl.h>
  31. #include <GL/glxproto.h>
  32. #include <inttypes.h>
  33. #include "indirect_size.h"
  34. #include "indirect_size_get.h"
  35. #include "indirect_dispatch.h"
  36. #include "glxserver.h"
  37. #include "glxbyteorder.h"
  38. #include "singlesize.h"
  39. #include "glxext.h"
  40. #include "indirect_table.h"
  41. #include "indirect_util.h"
  42. #define __GLX_PAD(a) (((a)+3)&~3)
  43. extern xGLXSingleReply __glXReply;
  44. GLint
  45. __glGetBooleanv_variable_size(GLenum e)
  46. {
  47. if (e == GL_COMPRESSED_TEXTURE_FORMATS) {
  48. GLint temp;
  49. glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &temp);
  50. return temp;
  51. }
  52. else {
  53. return 0;
  54. }
  55. }
  56. /**
  57. * Get a properly aligned buffer to hold reply data.
  58. *
  59. * \warning
  60. * This function assumes that \c local_buffer is already properly aligned.
  61. * It also assumes that \c alignment is a power of two.
  62. */
  63. void *
  64. __glXGetAnswerBuffer(__GLXclientState * cl, size_t required_size,
  65. void *local_buffer, size_t local_size, unsigned alignment)
  66. {
  67. void *buffer = local_buffer;
  68. const intptr_t mask = alignment - 1;
  69. if (local_size < required_size) {
  70. size_t worst_case_size;
  71. intptr_t temp_buf;
  72. if (required_size < SIZE_MAX - alignment)
  73. worst_case_size = required_size + alignment;
  74. else
  75. return NULL;
  76. if (cl->returnBufSize < worst_case_size) {
  77. void *temp = realloc(cl->returnBuf, worst_case_size);
  78. if (temp == NULL) {
  79. return NULL;
  80. }
  81. cl->returnBuf = temp;
  82. cl->returnBufSize = worst_case_size;
  83. }
  84. temp_buf = (intptr_t) cl->returnBuf;
  85. temp_buf = (temp_buf + mask) & ~mask;
  86. buffer = (void *) temp_buf;
  87. }
  88. return buffer;
  89. }
  90. /**
  91. * Send a GLX reply to the client.
  92. *
  93. * Technically speaking, there are several different ways to encode a GLX
  94. * reply. The primary difference is whether or not certain fields (e.g.,
  95. * retval, size, and "pad3") are set. This function gets around that by
  96. * always setting all of the fields to "reasonable" values. This does no
  97. * harm to clients, but it does make the server-side code much more compact.
  98. */
  99. void
  100. __glXSendReply(ClientPtr client, const void *data, size_t elements,
  101. size_t element_size, GLboolean always_array, CARD32 retval)
  102. {
  103. size_t reply_ints = 0;
  104. if (__glXErrorOccured()) {
  105. elements = 0;
  106. }
  107. else if ((elements > 1) || always_array) {
  108. reply_ints = bytes_to_int32(elements * element_size);
  109. }
  110. __glXReply.length = reply_ints;
  111. __glXReply.type = X_Reply;
  112. __glXReply.sequenceNumber = client->sequence;
  113. __glXReply.size = elements;
  114. __glXReply.retval = retval;
  115. /* It is faster on almost always every architecture to just copy the 8
  116. * bytes, even when not necessary, than check to see of the value of
  117. * elements requires it. Copying the data when not needed will do no
  118. * harm.
  119. */
  120. (void) memcpy(&__glXReply.pad3, data, 8);
  121. WriteToClient(client, sz_xGLXSingleReply, &__glXReply);
  122. if (reply_ints != 0) {
  123. WriteToClient(client, reply_ints * 4, data);
  124. }
  125. }
  126. /**
  127. * Send a GLX reply to the client.
  128. *
  129. * Technically speaking, there are several different ways to encode a GLX
  130. * reply. The primary difference is whether or not certain fields (e.g.,
  131. * retval, size, and "pad3") are set. This function gets around that by
  132. * always setting all of the fields to "reasonable" values. This does no
  133. * harm to clients, but it does make the server-side code much more compact.
  134. *
  135. * \warning
  136. * This function assumes that values stored in \c data will be byte-swapped
  137. * by the caller if necessary.
  138. */
  139. void
  140. __glXSendReplySwap(ClientPtr client, const void *data, size_t elements,
  141. size_t element_size, GLboolean always_array, CARD32 retval)
  142. {
  143. size_t reply_ints = 0;
  144. if (__glXErrorOccured()) {
  145. elements = 0;
  146. }
  147. else if ((elements > 1) || always_array) {
  148. reply_ints = bytes_to_int32(elements * element_size);
  149. }
  150. __glXReply.length = bswap_32(reply_ints);
  151. __glXReply.type = X_Reply;
  152. __glXReply.sequenceNumber = bswap_16(client->sequence);
  153. __glXReply.size = bswap_32(elements);
  154. __glXReply.retval = bswap_32(retval);
  155. /* It is faster on almost always every architecture to just copy the 8
  156. * bytes, even when not necessary, than check to see of the value of
  157. * elements requires it. Copying the data when not needed will do no
  158. * harm.
  159. */
  160. (void) memcpy(&__glXReply.pad3, data, 8);
  161. WriteToClient(client, sz_xGLXSingleReply, &__glXReply);
  162. if (reply_ints != 0) {
  163. WriteToClient(client, reply_ints * 4, data);
  164. }
  165. }
  166. static int
  167. get_decode_index(const struct __glXDispatchInfo *dispatch_info, unsigned opcode)
  168. {
  169. int remaining_bits;
  170. int next_remain;
  171. const int_fast16_t *const tree = dispatch_info->dispatch_tree;
  172. int_fast16_t index;
  173. remaining_bits = dispatch_info->bits;
  174. if (opcode >= (1U << remaining_bits)) {
  175. return -1;
  176. }
  177. index = 0;
  178. for ( /* empty */ ; remaining_bits > 0; remaining_bits = next_remain) {
  179. unsigned mask;
  180. unsigned child_index;
  181. /* Calculate the slice of bits used by this node.
  182. *
  183. * If remaining_bits = 8 and tree[index] = 3, the mask of just the
  184. * remaining bits is 0x00ff and the mask for the remaining bits after
  185. * this node is 0x001f. By taking 0x00ff & ~0x001f, we get 0x00e0.
  186. * This masks the 3 bits that we would want for this node.
  187. */
  188. next_remain = remaining_bits - tree[index];
  189. mask = ((1 << remaining_bits) - 1) & ~((1 << next_remain) - 1);
  190. /* Using the mask, calculate the index of the opcode in the node.
  191. * With that index, fetch the index of the next node.
  192. */
  193. child_index = (opcode & mask) >> next_remain;
  194. index = tree[index + 1 + child_index];
  195. /* If the next node is an empty leaf, the opcode is for a non-existant
  196. * function. We're done.
  197. *
  198. * If the next node is a non-empty leaf, look up the function pointer
  199. * and return it.
  200. */
  201. if (index == EMPTY_LEAF) {
  202. return -1;
  203. }
  204. else if (IS_LEAF_INDEX(index)) {
  205. unsigned func_index;
  206. /* The value stored in the tree for a leaf node is the base of
  207. * the function pointers for that leaf node. The offset for the
  208. * function for a particular opcode is the remaining bits in the
  209. * opcode.
  210. */
  211. func_index = -index;
  212. func_index += opcode & ((1 << next_remain) - 1);
  213. return func_index;
  214. }
  215. }
  216. /* We should *never* get here!!!
  217. */
  218. return -1;
  219. }
  220. void *
  221. __glXGetProtocolDecodeFunction(const struct __glXDispatchInfo *dispatch_info,
  222. int opcode, int swapped_version)
  223. {
  224. const int func_index = get_decode_index(dispatch_info, opcode);
  225. return (func_index < 0)
  226. ? NULL
  227. : (void *) dispatch_info->
  228. dispatch_functions[func_index][swapped_version];
  229. }
  230. int
  231. __glXGetProtocolSizeData(const struct __glXDispatchInfo *dispatch_info,
  232. int opcode, __GLXrenderSizeData * data)
  233. {
  234. if (dispatch_info->size_table != NULL) {
  235. const int func_index = get_decode_index(dispatch_info, opcode);
  236. if ((func_index >= 0)
  237. && (dispatch_info->size_table[func_index][0] != 0)) {
  238. const int var_offset = dispatch_info->size_table[func_index][1];
  239. data->bytes = dispatch_info->size_table[func_index][0];
  240. data->varsize = (var_offset != ~0)
  241. ? dispatch_info->size_func_table[var_offset]
  242. : NULL;
  243. return 0;
  244. }
  245. }
  246. return -1;
  247. }