#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 );
}
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);
}
}
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) {
return -1;
}
break;
case GL_FOG_COORD_ARRAY:
case GL_INDEX_ARRAY:
if (numVals != 1) {
return -1;
}
break;
case GL_EDGE_FLAG_ARRAY:
if ((numVals != 1) && (datatype != GL_UNSIGNED_BYTE)) {
return -1;
}
break;
default:
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 );
}
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;
}