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