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