xserver-multidpi/glx/rensize.c
Adam Jackson 69b79c1a66 Update to SGI FreeB 2.0.
Under the terms of version 1.1, "once Covered Code has been published
under a particular version of the License, Recipient may, for the
duration of the License, continue to use it under the terms of that
version, or choose to use such Covered Code under the terms of any
subsequent version published by SGI."

FreeB 2.0 license refers to "dates of first publication".  They are here
taken to be 1991-2000, as noted in the original license text:

 ** Original Code. The Original Code is: OpenGL Sample Implementation,
 ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
 ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
 ** Copyright in any portions created by third parties is as indicated
 ** elsewhere herein. All Rights Reserved.

Official FreeB 2.0 text:

http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf

As always, this code has not been tested for conformance with the OpenGL
specification.  OpenGL conformance testing is available from
http://khronos.org/ and is required for use of the OpenGL logo in
product advertising and promotion.
2008-09-19 12:02:28 -04:00

419 lines
12 KiB
C

/*
* SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
* Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice including the dates of first publication and
* either this permission notice or a reference to
* http://oss.sgi.com/projects/FreeB/
* shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of Silicon Graphics, Inc.
* shall not be used in advertising or otherwise to promote the sale, use or
* other dealings in this Software without prior written authorization from
* Silicon Graphics, Inc.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <GL/gl.h>
#include "glxserver.h"
#include "GL/glxproto.h"
#include "unpack.h"
#include "indirect_size.h"
#include "indirect_reqsize.h"
#define SWAPL(a) \
(((a & 0xff000000U)>>24) | ((a & 0xff0000U)>>8) | \
((a & 0xff00U)<<8) | ((a & 0xffU)<<24))
static int Map1Size( GLint k, GLint order)
{
if (order <= 0 || k < 0) return -1;
return k * order;
}
int __glXMap1dReqSize( const GLbyte *pc, Bool swap )
{
GLenum target;
GLint order, k;
target = *(GLenum*) (pc + 16);
order = *(GLint*) (pc + 20);
if (swap) {
target = SWAPL( target );
order = SWAPL( order );
}
k = __glMap1d_size( target );
return 8 * Map1Size( k, order );
}
int __glXMap1fReqSize( const GLbyte *pc, Bool swap )
{
GLenum target;
GLint order, k;
target = *(GLenum *)(pc + 0);
order = *(GLint *)(pc + 12);
if (swap) {
target = SWAPL( target );
order = SWAPL( order );
}
k = __glMap1f_size(target);
return 4 * Map1Size(k, order);
}
static int Map2Size(int k, int majorOrder, int minorOrder)
{
if (majorOrder <= 0 || minorOrder <= 0 || k < 0) return -1;
return k * majorOrder * minorOrder;
}
int __glXMap2dReqSize( const GLbyte *pc, Bool swap )
{
GLenum target;
GLint uorder, vorder, k;
target = *(GLenum *)(pc + 32);
uorder = *(GLint *)(pc + 36);
vorder = *(GLint *)(pc + 40);
if (swap) {
target = SWAPL( target );
uorder = SWAPL( uorder );
vorder = SWAPL( vorder );
}
k = __glMap2d_size( target );
return 8 * Map2Size( k, uorder, vorder );
}
int __glXMap2fReqSize( const GLbyte *pc, Bool swap )
{
GLenum target;
GLint uorder, vorder, k;
target = *(GLenum *)(pc + 0);
uorder = *(GLint *)(pc + 12);
vorder = *(GLint *)(pc + 24);
if (swap) {
target = SWAPL( target );
uorder = SWAPL( uorder );
vorder = SWAPL( vorder );
}
k = __glMap2f_size( target );
return 4 * Map2Size( k, uorder, vorder );
}
/**
* Calculate the size of an image.
*
* The size of an image sent to the server from the client or sent from the
* server to the client is calculated. The size is based on the dimensions
* of the image, the type of pixel data, padding in the image, and the
* alignment requirements of the image.
*
* \param format Format of the pixels. Same as the \c format parameter
* to \c glTexImage1D
* \param type Type of the pixel data. Same as the \c type parameter
* to \c glTexImage1D
* \param target Typically the texture target of the image. If the
* target is one of \c GL_PROXY_*, the size returned is
* always zero. For uses that do not have a texture target
* (e.g, glDrawPixels), zero should be specified.
* \param w Width of the image data. Must be >= 1.
* \param h Height of the image data. Must be >= 1, even for 1D
* images.
* \param d Depth of the image data. Must be >= 1, even for 1D or
* 2D images.
* \param imageHeight If non-zero, defines the true height of a volumetric
* image. This value will be used instead of \c h for
* calculating the size of the image.
* \param rowLength If non-zero, defines the true width of an image. This
* value will be used instead of \c w for calculating the
* size of the image.
* \param skipImages Number of extra layers of image data in a volumtric
* image that are to be skipped before the real data.
* \param skipRows Number of extra rows of image data in an image that are
* to be skipped before the real data.
* \param alignment Specifies the alignment for the start of each pixel row
* in memory. This value must be one of 1, 2, 4, or 8.
*
* \returns
* The size of the image is returned. If the specified \c format and \c type
* are invalid, -1 is returned. If \c target is one of \c GL_PROXY_*, zero
* is returned.
*/
int __glXImageSize( GLenum format, GLenum type, GLenum target,
GLsizei w, GLsizei h, GLsizei d,
GLint imageHeight, GLint rowLength,
GLint skipImages, GLint skipRows, GLint alignment )
{
GLint bytesPerElement, elementsPerGroup, groupsPerRow;
GLint groupSize, rowSize, padding, imageSize;
if (w < 0 || h < 0 || d < 0 ||
(type == GL_BITMAP &&
(format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX))) {
return -1;
}
if (w==0 || h==0 || d == 0) return 0;
switch( target ) {
case GL_PROXY_TEXTURE_1D:
case GL_PROXY_TEXTURE_2D:
case GL_PROXY_TEXTURE_3D:
case GL_PROXY_TEXTURE_4D_SGIS:
case GL_PROXY_TEXTURE_CUBE_MAP:
case GL_PROXY_TEXTURE_RECTANGLE_ARB:
case GL_PROXY_HISTOGRAM:
case GL_PROXY_COLOR_TABLE:
case GL_PROXY_TEXTURE_COLOR_TABLE_SGI:
case GL_PROXY_POST_CONVOLUTION_COLOR_TABLE:
case GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE:
case GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP:
return 0;
}
if (type == GL_BITMAP) {
if (rowLength > 0) {
groupsPerRow = rowLength;
} else {
groupsPerRow = w;
}
rowSize = (groupsPerRow + 7) >> 3;
padding = (rowSize % alignment);
if (padding) {
rowSize += alignment - padding;
}
return ((h + skipRows) * rowSize);
} else {
switch(format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_INTENSITY:
elementsPerGroup = 1;
break;
case GL_422_EXT:
case GL_422_REV_EXT:
case GL_422_AVERAGE_EXT:
case GL_422_REV_AVERAGE_EXT:
case GL_DEPTH_STENCIL_NV:
case GL_DEPTH_STENCIL_MESA:
case GL_YCBCR_MESA:
case GL_LUMINANCE_ALPHA:
elementsPerGroup = 2;
break;
case GL_RGB:
case GL_BGR:
elementsPerGroup = 3;
break;
case GL_RGBA:
case GL_BGRA:
case GL_ABGR_EXT:
elementsPerGroup = 4;
break;
default:
return -1;
}
switch(type) {
case GL_UNSIGNED_BYTE:
case GL_BYTE:
bytesPerElement = 1;
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
bytesPerElement = 1;
elementsPerGroup = 1;
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
bytesPerElement = 2;
break;
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
case GL_UNSIGNED_SHORT_8_8_APPLE:
case GL_UNSIGNED_SHORT_8_8_REV_APPLE:
case GL_UNSIGNED_SHORT_15_1_MESA:
case GL_UNSIGNED_SHORT_1_15_REV_MESA:
bytesPerElement = 2;
elementsPerGroup = 1;
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
bytesPerElement = 4;
break;
case GL_UNSIGNED_INT_8_8_8_8:
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_INT_10_10_10_2:
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_24_8_NV:
case GL_UNSIGNED_INT_24_8_MESA:
case GL_UNSIGNED_INT_8_24_REV_MESA:
bytesPerElement = 4;
elementsPerGroup = 1;
break;
default:
return -1;
}
groupSize = bytesPerElement * elementsPerGroup;
if (rowLength > 0) {
groupsPerRow = rowLength;
} else {
groupsPerRow = w;
}
rowSize = groupsPerRow * groupSize;
padding = (rowSize % alignment);
if (padding) {
rowSize += alignment - padding;
}
if (imageHeight > 0) {
imageSize = (imageHeight + skipRows) * rowSize;
} else {
imageSize = (h + skipRows) * rowSize;
}
return ((d + skipImages) * imageSize);
}
}
/* XXX this is used elsewhere - should it be exported from glxserver.h? */
int __glXTypeSize(GLenum enm)
{
switch(enm) {
case GL_BYTE: return sizeof(GLbyte);
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
case GL_SHORT: return sizeof(GLshort);
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
case GL_INT: return sizeof(GLint);
case GL_UNSIGNED_INT: return sizeof(GLint);
case GL_FLOAT: return sizeof(GLfloat);
case GL_DOUBLE: return sizeof(GLdouble);
default: return -1;
}
}
int __glXDrawArraysReqSize( const GLbyte *pc, Bool swap )
{
__GLXdispatchDrawArraysHeader *hdr = (__GLXdispatchDrawArraysHeader *) pc;
__GLXdispatchDrawArraysComponentHeader *compHeader;
GLint numVertexes = hdr->numVertexes;
GLint numComponents = hdr->numComponents;
GLint arrayElementSize = 0;
int i;
if (swap) {
numVertexes = SWAPL( numVertexes );
numComponents = SWAPL( numComponents );
}
pc += sizeof(__GLXdispatchDrawArraysHeader);
compHeader = (__GLXdispatchDrawArraysComponentHeader *) pc;
for (i=0; i<numComponents; i++) {
GLenum datatype = compHeader[i].datatype;
GLint numVals = compHeader[i].numVals;
GLint component = compHeader[i].component;
if (swap) {
datatype = SWAPL( datatype );
numVals = SWAPL( numVals );
component = SWAPL( component );
}
switch (component) {
case GL_VERTEX_ARRAY:
case GL_COLOR_ARRAY:
case GL_TEXTURE_COORD_ARRAY:
break;
case GL_SECONDARY_COLOR_ARRAY:
case GL_NORMAL_ARRAY:
if (numVals != 3) {
/* bad size */
return -1;
}
break;
case GL_FOG_COORD_ARRAY:
case GL_INDEX_ARRAY:
if (numVals != 1) {
/* bad size */
return -1;
}
break;
case GL_EDGE_FLAG_ARRAY:
if ((numVals != 1) && (datatype != GL_UNSIGNED_BYTE)) {
/* bad size or bad type */
return -1;
}
break;
default:
/* unknown component type */
return -1;
}
arrayElementSize += __GLX_PAD(numVals * __glXTypeSize(datatype));
pc += sizeof(__GLXdispatchDrawArraysComponentHeader);
}
return ((numComponents * sizeof(__GLXdispatchDrawArraysComponentHeader)) +
(numVertexes * arrayElementSize));
}
int __glXSeparableFilter2DReqSize( const GLbyte *pc, Bool swap )
{
__GLXdispatchConvolutionFilterHeader *hdr =
(__GLXdispatchConvolutionFilterHeader *) pc;
GLint image1size, image2size;
GLenum format = hdr->format;
GLenum type = hdr->type;
GLint w = hdr->width;
GLint h = hdr->height;
GLint rowLength = hdr->rowLength;
GLint alignment = hdr->alignment;
if (swap) {
format = SWAPL( format );
type = SWAPL( type );
w = SWAPL( w );
h = SWAPL( h );
rowLength = SWAPL( rowLength );
alignment = SWAPL( alignment );
}
/* XXX Should rowLength be used for either or both image? */
image1size = __glXImageSize( format, type, 0, w, 1, 1,
0, rowLength, 0, 0, alignment );
image1size = __GLX_PAD(image1size);
image2size = __glXImageSize( format, type, 0, h, 1, 1,
0, rowLength, 0, 0, alignment );
return image1size + image2size;
}