rensize.c revision f7df2e56
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 47__glXMap1dReqSize(const GLbyte * pc, Bool swap, int reqlen) 48{ 49 GLenum target; 50 GLint order; 51 52 target = *(GLenum *) (pc + 16); 53 order = *(GLint *) (pc + 20); 54 if (swap) { 55 target = SWAPL(target); 56 order = SWAPL(order); 57 } 58 if (order < 1) 59 return -1; 60 return safe_mul(8, safe_mul(__glMap1d_size(target), order)); 61} 62 63int 64__glXMap1fReqSize(const GLbyte * pc, Bool swap, int reqlen) 65{ 66 GLenum target; 67 GLint order; 68 69 target = *(GLenum *) (pc + 0); 70 order = *(GLint *) (pc + 12); 71 if (swap) { 72 target = SWAPL(target); 73 order = SWAPL(order); 74 } 75 if (order < 1) 76 return -1; 77 return safe_mul(4, safe_mul(__glMap1f_size(target), order)); 78} 79 80static int 81Map2Size(int k, int majorOrder, int minorOrder) 82{ 83 if (majorOrder < 1 || minorOrder < 1) 84 return -1; 85 return safe_mul(k, safe_mul(majorOrder, minorOrder)); 86} 87 88int 89__glXMap2dReqSize(const GLbyte * pc, Bool swap, int reqlen) 90{ 91 GLenum target; 92 GLint uorder, vorder; 93 94 target = *(GLenum *) (pc + 32); 95 uorder = *(GLint *) (pc + 36); 96 vorder = *(GLint *) (pc + 40); 97 if (swap) { 98 target = SWAPL(target); 99 uorder = SWAPL(uorder); 100 vorder = SWAPL(vorder); 101 } 102 return safe_mul(8, Map2Size(__glMap2d_size(target), uorder, vorder)); 103} 104 105int 106__glXMap2fReqSize(const GLbyte * pc, Bool swap, int reqlen) 107{ 108 GLenum target; 109 GLint uorder, vorder; 110 111 target = *(GLenum *) (pc + 0); 112 uorder = *(GLint *) (pc + 12); 113 vorder = *(GLint *) (pc + 24); 114 if (swap) { 115 target = SWAPL(target); 116 uorder = SWAPL(uorder); 117 vorder = SWAPL(vorder); 118 } 119 return safe_mul(4, Map2Size(__glMap2f_size(target), 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 162__glXImageSize(GLenum format, GLenum type, GLenum target, 163 GLsizei w, GLsizei h, GLsizei d, 164 GLint imageHeight, GLint rowLength, 165 GLint skipImages, GLint skipRows, GLint alignment) 166{ 167 GLint bytesPerElement, elementsPerGroup, groupsPerRow; 168 GLint groupSize, rowSize, padding, imageSize; 169 170 if (w == 0 || h == 0 || d == 0) 171 return 0; 172 173 if (w < 0 || h < 0 || d < 0 || 174 (type == GL_BITMAP && 175 (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX))) { 176 return -1; 177 } 178 179 /* proxy targets have no data */ 180 switch (target) { 181 case GL_PROXY_TEXTURE_1D: 182 case GL_PROXY_TEXTURE_2D: 183 case GL_PROXY_TEXTURE_3D: 184 case GL_PROXY_TEXTURE_4D_SGIS: 185 case GL_PROXY_TEXTURE_CUBE_MAP: 186 case GL_PROXY_TEXTURE_RECTANGLE_ARB: 187 case GL_PROXY_HISTOGRAM: 188 case GL_PROXY_COLOR_TABLE: 189 case GL_PROXY_TEXTURE_COLOR_TABLE_SGI: 190 case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE: 191 case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE: 192 case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP: 193 return 0; 194 } 195 196 /* real data has to have real sizes */ 197 if (imageHeight < 0 || rowLength < 0 || skipImages < 0 || skipRows < 0) 198 return -1; 199 if (alignment != 1 && alignment != 2 && alignment != 4 && alignment != 8) 200 return -1; 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 if (rowSize < 0) 211 return -1; 212 padding = (rowSize % alignment); 213 if (padding) { 214 rowSize += alignment - padding; 215 } 216 217 return safe_mul(safe_add(h, skipRows), rowSize); 218 } 219 else { 220 switch (format) { 221 case GL_COLOR_INDEX: 222 case GL_STENCIL_INDEX: 223 case GL_DEPTH_COMPONENT: 224 case GL_RED: 225 case GL_GREEN: 226 case GL_BLUE: 227 case GL_ALPHA: 228 case GL_LUMINANCE: 229 case GL_INTENSITY: 230 case GL_RED_INTEGER_EXT: 231 case GL_GREEN_INTEGER_EXT: 232 case GL_BLUE_INTEGER_EXT: 233 case GL_ALPHA_INTEGER_EXT: 234 case GL_LUMINANCE_INTEGER_EXT: 235 elementsPerGroup = 1; 236 break; 237 case GL_422_EXT: 238 case GL_422_REV_EXT: 239 case GL_422_AVERAGE_EXT: 240 case GL_422_REV_AVERAGE_EXT: 241 case GL_DEPTH_STENCIL_NV: 242 case GL_DEPTH_STENCIL_MESA: 243 case GL_YCBCR_422_APPLE: 244 case GL_YCBCR_MESA: 245 case GL_LUMINANCE_ALPHA: 246 case GL_LUMINANCE_ALPHA_INTEGER_EXT: 247 elementsPerGroup = 2; 248 break; 249 case GL_RGB: 250 case GL_BGR: 251 case GL_RGB_INTEGER_EXT: 252 case GL_BGR_INTEGER_EXT: 253 elementsPerGroup = 3; 254 break; 255 case GL_RGBA: 256 case GL_BGRA: 257 case GL_RGBA_INTEGER_EXT: 258 case GL_BGRA_INTEGER_EXT: 259 case GL_ABGR_EXT: 260 elementsPerGroup = 4; 261 break; 262 default: 263 return -1; 264 } 265 switch (type) { 266 case GL_UNSIGNED_BYTE: 267 case GL_BYTE: 268 bytesPerElement = 1; 269 break; 270 case GL_UNSIGNED_BYTE_3_3_2: 271 case GL_UNSIGNED_BYTE_2_3_3_REV: 272 bytesPerElement = 1; 273 elementsPerGroup = 1; 274 break; 275 case GL_UNSIGNED_SHORT: 276 case GL_SHORT: 277 bytesPerElement = 2; 278 break; 279 case GL_UNSIGNED_SHORT_5_6_5: 280 case GL_UNSIGNED_SHORT_5_6_5_REV: 281 case GL_UNSIGNED_SHORT_4_4_4_4: 282 case GL_UNSIGNED_SHORT_4_4_4_4_REV: 283 case GL_UNSIGNED_SHORT_5_5_5_1: 284 case GL_UNSIGNED_SHORT_1_5_5_5_REV: 285 case GL_UNSIGNED_SHORT_8_8_APPLE: 286 case GL_UNSIGNED_SHORT_8_8_REV_APPLE: 287 case GL_UNSIGNED_SHORT_15_1_MESA: 288 case GL_UNSIGNED_SHORT_1_15_REV_MESA: 289 bytesPerElement = 2; 290 elementsPerGroup = 1; 291 break; 292 case GL_INT: 293 case GL_UNSIGNED_INT: 294 case GL_FLOAT: 295 bytesPerElement = 4; 296 break; 297 case GL_UNSIGNED_INT_8_8_8_8: 298 case GL_UNSIGNED_INT_8_8_8_8_REV: 299 case GL_UNSIGNED_INT_10_10_10_2: 300 case GL_UNSIGNED_INT_2_10_10_10_REV: 301 case GL_UNSIGNED_INT_24_8_NV: 302 case GL_UNSIGNED_INT_24_8_MESA: 303 case GL_UNSIGNED_INT_8_24_REV_MESA: 304 bytesPerElement = 4; 305 elementsPerGroup = 1; 306 break; 307 default: 308 return -1; 309 } 310 /* known safe by the switches above, not checked */ 311 groupSize = bytesPerElement * elementsPerGroup; 312 if (rowLength > 0) { 313 groupsPerRow = rowLength; 314 } 315 else { 316 groupsPerRow = w; 317 } 318 319 if ((rowSize = safe_mul(groupsPerRow, groupSize)) < 0) 320 return -1; 321 padding = (rowSize % alignment); 322 if (padding) { 323 rowSize += alignment - padding; 324 } 325 326 if (imageHeight > 0) 327 h = imageHeight; 328 h = safe_add(h, skipRows); 329 330 imageSize = safe_mul(h, rowSize); 331 332 return safe_mul(safe_add(d, skipImages), imageSize); 333 } 334} 335 336/* XXX this is used elsewhere - should it be exported from glxserver.h? */ 337int 338__glXTypeSize(GLenum enm) 339{ 340 switch (enm) { 341 case GL_BYTE: 342 return sizeof(GLbyte); 343 case GL_UNSIGNED_BYTE: 344 return sizeof(GLubyte); 345 case GL_SHORT: 346 return sizeof(GLshort); 347 case GL_UNSIGNED_SHORT: 348 return sizeof(GLushort); 349 case GL_INT: 350 return sizeof(GLint); 351 case GL_UNSIGNED_INT: 352 return sizeof(GLint); 353 case GL_FLOAT: 354 return sizeof(GLfloat); 355 case GL_DOUBLE: 356 return sizeof(GLdouble); 357 default: 358 return -1; 359 } 360} 361 362int 363__glXDrawArraysReqSize(const GLbyte * pc, Bool swap, int reqlen) 364{ 365 __GLXdispatchDrawArraysHeader *hdr = (__GLXdispatchDrawArraysHeader *) pc; 366 __GLXdispatchDrawArraysComponentHeader *compHeader; 367 GLint numVertexes = hdr->numVertexes; 368 GLint numComponents = hdr->numComponents; 369 GLint arrayElementSize = 0; 370 GLint x, size; 371 int i; 372 373 if (swap) { 374 numVertexes = SWAPL(numVertexes); 375 numComponents = SWAPL(numComponents); 376 } 377 378 pc += sizeof(__GLXdispatchDrawArraysHeader); 379 reqlen -= sizeof(__GLXdispatchDrawArraysHeader); 380 381 size = safe_mul(sizeof(__GLXdispatchDrawArraysComponentHeader), 382 numComponents); 383 if (size < 0 || reqlen < 0 || reqlen < size) 384 return -1; 385 386 compHeader = (__GLXdispatchDrawArraysComponentHeader *) pc; 387 388 for (i = 0; i < numComponents; i++) { 389 GLenum datatype = compHeader[i].datatype; 390 GLint numVals = compHeader[i].numVals; 391 GLint component = compHeader[i].component; 392 393 if (swap) { 394 datatype = SWAPL(datatype); 395 numVals = SWAPL(numVals); 396 component = SWAPL(component); 397 } 398 399 switch (component) { 400 case GL_VERTEX_ARRAY: 401 case GL_COLOR_ARRAY: 402 case GL_TEXTURE_COORD_ARRAY: 403 break; 404 case GL_SECONDARY_COLOR_ARRAY: 405 case GL_NORMAL_ARRAY: 406 if (numVals != 3) { 407 /* bad size */ 408 return -1; 409 } 410 break; 411 case GL_FOG_COORD_ARRAY: 412 case GL_INDEX_ARRAY: 413 if (numVals != 1) { 414 /* bad size */ 415 return -1; 416 } 417 break; 418 case GL_EDGE_FLAG_ARRAY: 419 if ((numVals != 1) && (datatype != GL_UNSIGNED_BYTE)) { 420 /* bad size or bad type */ 421 return -1; 422 } 423 break; 424 default: 425 /* unknown component type */ 426 return -1; 427 } 428 429 x = safe_pad(safe_mul(numVals, __glXTypeSize(datatype))); 430 if ((arrayElementSize = safe_add(arrayElementSize, x)) < 0) 431 return -1; 432 433 pc += sizeof(__GLXdispatchDrawArraysComponentHeader); 434 } 435 436 return safe_add(size, safe_mul(numVertexes, arrayElementSize)); 437} 438 439int 440__glXSeparableFilter2DReqSize(const GLbyte * pc, Bool swap, int reqlen) 441{ 442 __GLXdispatchConvolutionFilterHeader *hdr = 443 (__GLXdispatchConvolutionFilterHeader *) pc; 444 445 GLint image1size, image2size; 446 GLenum format = hdr->format; 447 GLenum type = hdr->type; 448 GLint w = hdr->width; 449 GLint h = hdr->height; 450 GLint rowLength = hdr->rowLength; 451 GLint alignment = hdr->alignment; 452 453 if (swap) { 454 format = SWAPL(format); 455 type = SWAPL(type); 456 w = SWAPL(w); 457 h = SWAPL(h); 458 rowLength = SWAPL(rowLength); 459 alignment = SWAPL(alignment); 460 } 461 462 /* XXX Should rowLength be used for either or both image? */ 463 image1size = __glXImageSize(format, type, 0, w, 1, 1, 464 0, rowLength, 0, 0, alignment); 465 image2size = __glXImageSize(format, type, 0, h, 1, 1, 466 0, rowLength, 0, 0, alignment); 467 return safe_add(safe_pad(image1size), image2size); 468} 469