Commit | Line | Data |
---|---|---|
a09e091a JB |
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 <GL/gl.h> | |
36 | #include "glxserver.h" | |
37 | #include "GL/glxproto.h" | |
38 | #include "unpack.h" | |
39 | #include "indirect_size.h" | |
40 | #include "indirect_reqsize.h" | |
41 | ||
42 | #define SWAPL(a) \ | |
43 | (((a & 0xff000000U)>>24) | ((a & 0xff0000U)>>8) | \ | |
44 | ((a & 0xff00U)<<8) | ((a & 0xffU)<<24)) | |
45 | ||
46 | static int | |
47 | Map1Size(GLint k, GLint order) | |
48 | { | |
49 | if (order <= 0 || k < 0) | |
50 | return -1; | |
51 | return k * order; | |
52 | } | |
53 | ||
54 | int | |
55 | __glXMap1dReqSize(const GLbyte * pc, Bool swap) | |
56 | { | |
57 | GLenum target; | |
58 | GLint order, k; | |
59 | ||
60 | target = *(GLenum *) (pc + 16); | |
61 | order = *(GLint *) (pc + 20); | |
62 | if (swap) { | |
63 | target = SWAPL(target); | |
64 | order = SWAPL(order); | |
65 | } | |
66 | k = __glMap1d_size(target); | |
67 | return 8 * Map1Size(k, order); | |
68 | } | |
69 | ||
70 | int | |
71 | __glXMap1fReqSize(const GLbyte * pc, Bool swap) | |
72 | { | |
73 | GLenum target; | |
74 | GLint order, k; | |
75 | ||
76 | target = *(GLenum *) (pc + 0); | |
77 | order = *(GLint *) (pc + 12); | |
78 | if (swap) { | |
79 | target = SWAPL(target); | |
80 | order = SWAPL(order); | |
81 | } | |
82 | k = __glMap1f_size(target); | |
83 | return 4 * Map1Size(k, order); | |
84 | } | |
85 | ||
86 | static int | |
87 | Map2Size(int k, int majorOrder, int minorOrder) | |
88 | { | |
89 | if (majorOrder <= 0 || minorOrder <= 0 || k < 0) | |
90 | return -1; | |
91 | return k * majorOrder * minorOrder; | |
92 | } | |
93 | ||
94 | int | |
95 | __glXMap2dReqSize(const GLbyte * pc, Bool swap) | |
96 | { | |
97 | GLenum target; | |
98 | GLint uorder, vorder, k; | |
99 | ||
100 | target = *(GLenum *) (pc + 32); | |
101 | uorder = *(GLint *) (pc + 36); | |
102 | vorder = *(GLint *) (pc + 40); | |
103 | if (swap) { | |
104 | target = SWAPL(target); | |
105 | uorder = SWAPL(uorder); | |
106 | vorder = SWAPL(vorder); | |
107 | } | |
108 | k = __glMap2d_size(target); | |
109 | return 8 * Map2Size(k, uorder, vorder); | |
110 | } | |
111 | ||
112 | int | |
113 | __glXMap2fReqSize(const GLbyte * pc, Bool swap) | |
114 | { | |
115 | GLenum target; | |
116 | GLint uorder, vorder, k; | |
117 | ||
118 | target = *(GLenum *) (pc + 0); | |
119 | uorder = *(GLint *) (pc + 12); | |
120 | vorder = *(GLint *) (pc + 24); | |
121 | if (swap) { | |
122 | target = SWAPL(target); | |
123 | uorder = SWAPL(uorder); | |
124 | vorder = SWAPL(vorder); | |
125 | } | |
126 | k = __glMap2f_size(target); | |
127 | return 4 * Map2Size(k, uorder, vorder); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Calculate the size of an image. | |
132 | * | |
133 | * The size of an image sent to the server from the client or sent from the | |
134 | * server to the client is calculated. The size is based on the dimensions | |
135 | * of the image, the type of pixel data, padding in the image, and the | |
136 | * alignment requirements of the image. | |
137 | * | |
138 | * \param format Format of the pixels. Same as the \c format parameter | |
139 | * to \c glTexImage1D | |
140 | * \param type Type of the pixel data. Same as the \c type parameter | |
141 | * to \c glTexImage1D | |
142 | * \param target Typically the texture target of the image. If the | |
143 | * target is one of \c GL_PROXY_*, the size returned is | |
144 | * always zero. For uses that do not have a texture target | |
145 | * (e.g, glDrawPixels), zero should be specified. | |
146 | * \param w Width of the image data. Must be >= 1. | |
147 | * \param h Height of the image data. Must be >= 1, even for 1D | |
148 | * images. | |
149 | * \param d Depth of the image data. Must be >= 1, even for 1D or | |
150 | * 2D images. | |
151 | * \param imageHeight If non-zero, defines the true height of a volumetric | |
152 | * image. This value will be used instead of \c h for | |
153 | * calculating the size of the image. | |
154 | * \param rowLength If non-zero, defines the true width of an image. This | |
155 | * value will be used instead of \c w for calculating the | |
156 | * size of the image. | |
157 | * \param skipImages Number of extra layers of image data in a volumtric | |
158 | * image that are to be skipped before the real data. | |
159 | * \param skipRows Number of extra rows of image data in an image that are | |
160 | * to be skipped before the real data. | |
161 | * \param alignment Specifies the alignment for the start of each pixel row | |
162 | * in memory. This value must be one of 1, 2, 4, or 8. | |
163 | * | |
164 | * \returns | |
165 | * The size of the image is returned. If the specified \c format and \c type | |
166 | * are invalid, -1 is returned. If \c target is one of \c GL_PROXY_*, zero | |
167 | * is returned. | |
168 | */ | |
169 | int | |
170 | __glXImageSize(GLenum format, GLenum type, GLenum target, | |
171 | GLsizei w, GLsizei h, GLsizei d, | |
172 | GLint imageHeight, GLint rowLength, | |
173 | GLint skipImages, GLint skipRows, GLint alignment) | |
174 | { | |
175 | GLint bytesPerElement, elementsPerGroup, groupsPerRow; | |
176 | GLint groupSize, rowSize, padding, imageSize; | |
177 | ||
178 | if (w < 0 || h < 0 || d < 0 || | |
179 | (type == GL_BITMAP && | |
180 | (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX))) { | |
181 | return -1; | |
182 | } | |
183 | if (w == 0 || h == 0 || d == 0) | |
184 | return 0; | |
185 | ||
186 | switch (target) { | |
187 | case GL_PROXY_TEXTURE_1D: | |
188 | case GL_PROXY_TEXTURE_2D: | |
189 | case GL_PROXY_TEXTURE_3D: | |
190 | case GL_PROXY_TEXTURE_4D_SGIS: | |
191 | case GL_PROXY_TEXTURE_CUBE_MAP: | |
192 | case GL_PROXY_TEXTURE_RECTANGLE_ARB: | |
193 | case GL_PROXY_HISTOGRAM: | |
194 | case GL_PROXY_COLOR_TABLE: | |
195 | case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: | |
196 | case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: | |
197 | case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: | |
198 | case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP: | |
199 | return 0; | |
200 | } | |
201 | ||
202 | if (type == GL_BITMAP) { | |
203 | if (rowLength > 0) { | |
204 | groupsPerRow = rowLength; | |
205 | } | |
206 | else { | |
207 | groupsPerRow = w; | |
208 | } | |
209 | rowSize = bits_to_bytes(groupsPerRow); | |
210 | padding = (rowSize % alignment); | |
211 | if (padding) { | |
212 | rowSize += alignment - padding; | |
213 | } | |
214 | return ((h + skipRows) * rowSize); | |
215 | } | |
216 | else { | |
217 | switch (format) { | |
218 | case GL_COLOR_INDEX: | |
219 | case GL_STENCIL_INDEX: | |
220 | case GL_DEPTH_COMPONENT: | |
221 | case GL_RED: | |
222 | case GL_GREEN: | |
223 | case GL_BLUE: | |
224 | case GL_ALPHA: | |
225 | case GL_LUMINANCE: | |
226 | case GL_INTENSITY: | |
227 | elementsPerGroup = 1; | |
228 | break; | |
229 | case GL_422_EXT: | |
230 | case GL_422_REV_EXT: | |
231 | case GL_422_AVERAGE_EXT: | |
232 | case GL_422_REV_AVERAGE_EXT: | |
233 | case GL_DEPTH_STENCIL_NV: | |
234 | case GL_DEPTH_STENCIL_MESA: | |
235 | case GL_YCBCR_MESA: | |
236 | case GL_LUMINANCE_ALPHA: | |
237 | elementsPerGroup = 2; | |
238 | break; | |
239 | case GL_RGB: | |
240 | case GL_BGR: | |
241 | elementsPerGroup = 3; | |
242 | break; | |
243 | case GL_RGBA: | |
244 | case GL_BGRA: | |
245 | case GL_ABGR_EXT: | |
246 | elementsPerGroup = 4; | |
247 | break; | |
248 | default: | |
249 | return -1; | |
250 | } | |
251 | switch (type) { | |
252 | case GL_UNSIGNED_BYTE: | |
253 | case GL_BYTE: | |
254 | bytesPerElement = 1; | |
255 | break; | |
256 | case GL_UNSIGNED_BYTE_3_3_2: | |
257 | case GL_UNSIGNED_BYTE_2_3_3_REV: | |
258 | bytesPerElement = 1; | |
259 | elementsPerGroup = 1; | |
260 | break; | |
261 | case GL_UNSIGNED_SHORT: | |
262 | case GL_SHORT: | |
263 | bytesPerElement = 2; | |
264 | break; | |
265 | case GL_UNSIGNED_SHORT_5_6_5: | |
266 | case GL_UNSIGNED_SHORT_5_6_5_REV: | |
267 | case GL_UNSIGNED_SHORT_4_4_4_4: | |
268 | case GL_UNSIGNED_SHORT_4_4_4_4_REV: | |
269 | case GL_UNSIGNED_SHORT_5_5_5_1: | |
270 | case GL_UNSIGNED_SHORT_1_5_5_5_REV: | |
271 | case GL_UNSIGNED_SHORT_8_8_APPLE: | |
272 | case GL_UNSIGNED_SHORT_8_8_REV_APPLE: | |
273 | case GL_UNSIGNED_SHORT_15_1_MESA: | |
274 | case GL_UNSIGNED_SHORT_1_15_REV_MESA: | |
275 | bytesPerElement = 2; | |
276 | elementsPerGroup = 1; | |
277 | break; | |
278 | case GL_INT: | |
279 | case GL_UNSIGNED_INT: | |
280 | case GL_FLOAT: | |
281 | bytesPerElement = 4; | |
282 | break; | |
283 | case GL_UNSIGNED_INT_8_8_8_8: | |
284 | case GL_UNSIGNED_INT_8_8_8_8_REV: | |
285 | case GL_UNSIGNED_INT_10_10_10_2: | |
286 | case GL_UNSIGNED_INT_2_10_10_10_REV: | |
287 | case GL_UNSIGNED_INT_24_8_NV: | |
288 | case GL_UNSIGNED_INT_24_8_MESA: | |
289 | case GL_UNSIGNED_INT_8_24_REV_MESA: | |
290 | bytesPerElement = 4; | |
291 | elementsPerGroup = 1; | |
292 | break; | |
293 | default: | |
294 | return -1; | |
295 | } | |
296 | groupSize = bytesPerElement * elementsPerGroup; | |
297 | if (rowLength > 0) { | |
298 | groupsPerRow = rowLength; | |
299 | } | |
300 | else { | |
301 | groupsPerRow = w; | |
302 | } | |
303 | rowSize = groupsPerRow * groupSize; | |
304 | padding = (rowSize % alignment); | |
305 | if (padding) { | |
306 | rowSize += alignment - padding; | |
307 | } | |
308 | if (imageHeight > 0) { | |
309 | imageSize = (imageHeight + skipRows) * rowSize; | |
310 | } | |
311 | else { | |
312 | imageSize = (h + skipRows) * rowSize; | |
313 | } | |
314 | return ((d + skipImages) * imageSize); | |
315 | } | |
316 | } | |
317 | ||
318 | /* XXX this is used elsewhere - should it be exported from glxserver.h? */ | |
319 | int | |
320 | __glXTypeSize(GLenum enm) | |
321 | { | |
322 | switch (enm) { | |
323 | case GL_BYTE: | |
324 | return sizeof(GLbyte); | |
325 | case GL_UNSIGNED_BYTE: | |
326 | return sizeof(GLubyte); | |
327 | case GL_SHORT: | |
328 | return sizeof(GLshort); | |
329 | case GL_UNSIGNED_SHORT: | |
330 | return sizeof(GLushort); | |
331 | case GL_INT: | |
332 | return sizeof(GLint); | |
333 | case GL_UNSIGNED_INT: | |
334 | return sizeof(GLint); | |
335 | case GL_FLOAT: | |
336 | return sizeof(GLfloat); | |
337 | case GL_DOUBLE: | |
338 | return sizeof(GLdouble); | |
339 | default: | |
340 | return -1; | |
341 | } | |
342 | } | |
343 | ||
344 | int | |
345 | __glXDrawArraysReqSize(const GLbyte * pc, Bool swap) | |
346 | { | |
347 | __GLXdispatchDrawArraysHeader *hdr = (__GLXdispatchDrawArraysHeader *) pc; | |
348 | __GLXdispatchDrawArraysComponentHeader *compHeader; | |
349 | GLint numVertexes = hdr->numVertexes; | |
350 | GLint numComponents = hdr->numComponents; | |
351 | GLint arrayElementSize = 0; | |
352 | int i; | |
353 | ||
354 | if (swap) { | |
355 | numVertexes = SWAPL(numVertexes); | |
356 | numComponents = SWAPL(numComponents); | |
357 | } | |
358 | ||
359 | pc += sizeof(__GLXdispatchDrawArraysHeader); | |
360 | compHeader = (__GLXdispatchDrawArraysComponentHeader *) pc; | |
361 | ||
362 | for (i = 0; i < numComponents; i++) { | |
363 | GLenum datatype = compHeader[i].datatype; | |
364 | GLint numVals = compHeader[i].numVals; | |
365 | GLint component = compHeader[i].component; | |
366 | ||
367 | if (swap) { | |
368 | datatype = SWAPL(datatype); | |
369 | numVals = SWAPL(numVals); | |
370 | component = SWAPL(component); | |
371 | } | |
372 | ||
373 | switch (component) { | |
374 | case GL_VERTEX_ARRAY: | |
375 | case GL_COLOR_ARRAY: | |
376 | case GL_TEXTURE_COORD_ARRAY: | |
377 | break; | |
378 | case GL_SECONDARY_COLOR_ARRAY: | |
379 | case GL_NORMAL_ARRAY: | |
380 | if (numVals != 3) { | |
381 | /* bad size */ | |
382 | return -1; | |
383 | } | |
384 | break; | |
385 | case GL_FOG_COORD_ARRAY: | |
386 | case GL_INDEX_ARRAY: | |
387 | if (numVals != 1) { | |
388 | /* bad size */ | |
389 | return -1; | |
390 | } | |
391 | break; | |
392 | case GL_EDGE_FLAG_ARRAY: | |
393 | if ((numVals != 1) && (datatype != GL_UNSIGNED_BYTE)) { | |
394 | /* bad size or bad type */ | |
395 | return -1; | |
396 | } | |
397 | break; | |
398 | default: | |
399 | /* unknown component type */ | |
400 | return -1; | |
401 | } | |
402 | ||
403 | arrayElementSize += __GLX_PAD(numVals * __glXTypeSize(datatype)); | |
404 | ||
405 | pc += sizeof(__GLXdispatchDrawArraysComponentHeader); | |
406 | } | |
407 | ||
408 | return ((numComponents * sizeof(__GLXdispatchDrawArraysComponentHeader)) + | |
409 | (numVertexes * arrayElementSize)); | |
410 | } | |
411 | ||
412 | int | |
413 | __glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap) | |
414 | { | |
415 | __GLXdispatchConvolutionFilterHeader *hdr = | |
416 | (__GLXdispatchConvolutionFilterHeader *) pc; | |
417 | ||
418 | GLint image1size, image2size; | |
419 | GLenum format = hdr->format; | |
420 | GLenum type = hdr->type; | |
421 | GLint w = hdr->width; | |
422 | GLint h = hdr->height; | |
423 | GLint rowLength = hdr->rowLength; | |
424 | GLint alignment = hdr->alignment; | |
425 | ||
426 | if (swap) { | |
427 | format = SWAPL(format); | |
428 | type = SWAPL(type); | |
429 | w = SWAPL(w); | |
430 | h = SWAPL(h); | |
431 | rowLength = SWAPL(rowLength); | |
432 | alignment = SWAPL(alignment); | |
433 | } | |
434 | ||
435 | /* XXX Should rowLength be used for either or both image? */ | |
436 | image1size = __glXImageSize(format, type, 0, w, 1, 1, | |
437 | 0, rowLength, 0, 0, alignment); | |
438 | image1size = __GLX_PAD(image1size); | |
439 | image2size = __glXImageSize(format, type, 0, h, 1, 1, | |
440 | 0, rowLength, 0, 0, alignment); | |
441 | return image1size + image2size; | |
442 | ||
443 | } |