Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 4348 → Rev 4349

/contrib/sdk/samples/Mesa/engdemo.c
0,0 → 1,1676
/*
* Demo of off-screen Mesa rendering
*
* See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
*
* If you want to render BIG images you'll probably have to increase
* MAX_WIDTH and MAX_Height in src/config.h.
*
* This program is in the public domain.
*
* Brian Paul
*
* PPM output provided by Joerg Schmalzl.
* ASCII PPM output added by Brian Paul.
*
* Usage: osdemo [filename]
*/
 
 
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define GL_GLEXT_PROTOTYPES
#include "GL/osmesa.h"
#include <GL/glext.h>
#include "GL/glu.h"
#include "shaderutil.h"
 
 
static int Width = 500;
static int Height = 400;
 
int check_events();
 
GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
GLfloat angle = 0.0;
 
GLboolean animate = GL_TRUE; /* Animation */
GLfloat eyesep = 5.0; /* Eye separation. */
GLfloat fix_point = 40.0; /* Fixation point distance. */
GLfloat left, right, asp; /* Stereo frustum params. */
 
void init( void );
void reshape( int width, int height );
void draw( void );
void idle();
void Key(unsigned char key, int x, int y);
 
typedef union __attribute__((packed))
{
uint32_t val;
struct
{
uint8_t state;
uint8_t code;
uint16_t ctrl_key;
};
}oskey_t;
 
static inline oskey_t get_key(void)
{
oskey_t val;
__asm__ __volatile__(
"int $0x40"
:"=eax"(val)
:"a"(2));
return val;
}
 
 
struct blit_call
{
int dstx;
int dsty;
int w;
int h;
 
int srcx;
int srcy;
int srcw;
int srch;
 
unsigned char *bitmap;
int stride;
};
 
static inline uint32_t wait_os_event(int time)
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(23),"b"(time));
return val;
};
 
static inline uint32_t get_os_button()
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(17));
return val>>8;
};
 
static inline void DrawWindow(int x, int y, int w, int h, char *name,
uint32_t workcolor, uint32_t style)
{
 
__asm__ __volatile__(
"int $0x40"
::"a"(0),
"b"((x << 16) | (w & 0xFFFF)),
"c"((y << 16) | (h & 0xFFFF)),
"d"((style << 24) | (workcolor & 0xFFFFFF)),
"D"(name));
};
 
static inline void Blit(void *bitmap, int dst_x, int dst_y,
int src_x, int src_y, int w, int h,
int src_w, int src_h, int stride)
{
volatile struct blit_call bc;
 
bc.dstx = dst_x;
bc.dsty = dst_y;
bc.w = w;
bc.h = h;
bc.srcx = src_x;
bc.srcy = src_y;
bc.srcw = src_w;
bc.srch = src_h;
bc.stride = stride;
bc.bitmap = bitmap;
 
__asm__ __volatile__(
"int $0x40"
::"a"(73),"b"(0),"c"(&bc.dstx));
 
};
 
 
#define XK_Left 176
#define XK_Right 179
#define XK_Up 178
#define XK_Down 177
 
 
int main(int argc, char *argv[])
{
OSMesaContext ctx;
void *buffer;
char *filename = NULL;
int ev;
int repeat=1;
 
/* Create an RGBA-mode context */
/* specify Z, stencil, accum sizes */
 
ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
if (!ctx) {
printf("OSMesaCreateContext failed!\n");
return 0;
}
 
/* Allocate the image buffer */
buffer = malloc( Width * Height * 4 * sizeof(GLubyte) );
if (!buffer) {
printf("Alloc image buffer failed!\n");
return 0;
}
 
// __asm__ __volatile__("int3");
 
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, Width, Height )) {
printf("OSMesaMakeCurrent failed!\n");
return 0;
}
 
{
int z, s, a;
glGetIntegerv(GL_DEPTH_BITS, &z);
glGetIntegerv(GL_STENCIL_BITS, &s);
glGetIntegerv(GL_ACCUM_RED_BITS, &a);
printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
}
 
reshape(Width, Height);
 
init();
draw();
 
printf("all done\n");
 
DrawWindow(10, 10, Width+9, Height+26, "OpenGL Engine Demo", 0x000000, 0x74);
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
 
while(repeat)
{
oskey_t key;
 
ev = wait_os_event(1);
switch(ev)
{
case 1:
DrawWindow(10, 10, Width+9, Width+26, NULL, 0x000000,0x74);
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
continue;
 
case 2:
key = get_key();
Key(key.code, 0, 0);
draw();
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
continue;
 
case 3:
if(get_os_button()==1)
repeat=0;
continue;
};
 
idle();
 
// angle += 70.0 * 0.05; /* 70 degrees per second */
// if (angle > 3600.0)
// angle -= 3600.0;
draw();
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
};
 
/* free the image buffer */
free( buffer );
 
/* destroy the context */
OSMesaDestroyContext( ctx );
 
return 0;
}
 
void exit(int code)
{
_exit(code);
 
}
 
#if 0
static char *FragProgFile = "CH11-toyball.frag";
static char *VertProgFile = "CH11-toyball.vert";
 
/* program/shader objects */
static GLuint fragShader;
static GLuint vertShader;
static GLuint program;
 
 
static struct uniform_info Uniforms[] = {
{ "LightDir", 1, GL_FLOAT_VEC4, { 0.57737, 0.57735, 0.57735, 0.0 }, -1 },
{ "HVector", 1, GL_FLOAT_VEC4, { 0.32506, 0.32506, 0.88808, 0.0 }, -1 },
{ "BallCenter", 1, GL_FLOAT_VEC4, { 0.0, 0.0, 0.0, 1.0 }, -1 },
{ "SpecularColor", 1, GL_FLOAT_VEC4, { 0.4, 0.4, 0.4, 60.0 }, -1 },
{ "Red", 1, GL_FLOAT_VEC4, { 0.6, 0.0, 0.0, 1.0 }, -1 },
{ "Blue", 1, GL_FLOAT_VEC4, { 0.0, 0.3, 0.6, 1.0 }, -1 },
{ "Yellow", 1, GL_FLOAT_VEC4, { 0.6, 0.5, 0.0, 1.0 }, -1 },
{ "HalfSpace0", 1, GL_FLOAT_VEC4, { 1.0, 0.0, 0.0, 0.2 }, -1 },
{ "HalfSpace1", 1, GL_FLOAT_VEC4, { 0.309016994, 0.951056516, 0.0, 0.2 }, -1 },
{ "HalfSpace2", 1, GL_FLOAT_VEC4, { -0.809016994, 0.587785252, 0.0, 0.2 }, -1 },
{ "HalfSpace3", 1, GL_FLOAT_VEC4, { -0.809016994, -0.587785252, 0.0, 0.2 }, -1 },
{ "HalfSpace4", 1, GL_FLOAT_VEC4, { 0.309116994, -0.951056516, 0.0, 0.2 }, -1 },
{ "InOrOutInit", 1, GL_FLOAT, { -3.0, 0, 0, 0 }, -1 },
{ "StripeWidth", 1, GL_FLOAT, { 0.3, 0, 0, 0 }, -1 },
{ "FWidth", 1, GL_FLOAT, { 0.005, 0, 0, 0 }, -1 },
END_OF_UNIFORMS
};
 
static GLint win = 0;
static GLboolean Anim = GL_FALSE;
static GLfloat TexRot = 0.0;
static GLfloat xRot = 0.0f, yRot = 0.0f, zRot = 0.0f;
 
 
void Idle(void)
{
TexRot += 2.0;
if (TexRot > 360.0)
TexRot -= 360.0;
}
 
 
void draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
 
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(TexRot, 0.0f, 1.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);
 
glutSolidSphere(2.0, 20, 10);
 
glPopMatrix();
 
}
 
 
void
reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -15.0f);
}
 
 
static void
CleanUp(void)
{
glDeleteShader(fragShader);
glDeleteShader(vertShader);
glDeleteProgram(program);
glutDestroyWindow(win);
}
 
 
 
void init(void)
{
// if (!ShadersSupported())
// exit(1);
 
vertShader = CompileShaderFile(GL_VERTEX_SHADER, VertProgFile);
fragShader = CompileShaderFile(GL_FRAGMENT_SHADER, FragProgFile);
program = LinkShaders(vertShader, fragShader);
 
glUseProgram(program);
 
SetUniformValues(program, Uniforms);
PrintUniforms(Uniforms);
 
assert(glGetError() == 0);
 
glClearColor(0.4f, 0.4f, 0.8f, 0.0f);
 
glEnable(GL_DEPTH_TEST);
 
glColor3f(1, 0, 0);
}
#endif
 
 
#if 0
static float Zrot = 0.0;
 
void draw( void )
{
glClearColor(0.3, 0.3, 0.3, 1);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
glEnable(GL_VERTEX_PROGRAM_NV);
 
glLoadIdentity();
glRotatef(Zrot, 0, 0, 1);
 
glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 0, GL_MODELVIEW, GL_IDENTITY_NV);
glPushMatrix();
 
glVertexAttrib3fNV(3, 1, 0.5, 0.25);
glBegin(GL_TRIANGLES);
#if 1
glVertexAttrib3fNV(3, 1.0, 0.0, 0.0);
glVertexAttrib2fNV(0, -0.5, -0.5);
glVertexAttrib3fNV(3, 0.0, 1.0, 0.0);
glVertexAttrib2fNV(0, 0.5, -0.5);
glVertexAttrib3fNV(3, 0.0, 0.0, 1.0);
glVertexAttrib2fNV(0, 0, 0.5);
#else
glVertex2f( -1, -1);
glVertex2f( 1, -1);
glVertex2f( 0, 1);
#endif
glEnd();
 
glPopMatrix();
 
}
 
 
void reshape( int width, int height )
{
glViewport( 0, 0, width, height );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
/* glFrustum( -2.0, 2.0, -2.0, 2.0, 5.0, 25.0 );*/
glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
/*glTranslatef( 0.0, 0.0, -15.0 );*/
}
 
void idle()
{
Zrot-=4.0;
};
 
void init( void )
{
static const char *prog1 =
"!!VP1.0\n"
"MOV o[COL0], v[COL0];\n"
#if 0
"MOV o[HPOS], v[OPOS];\n"
#else
"DP4 o[HPOS].x, v[OPOS], c[0];\n"
"DP4 o[HPOS].y, v[OPOS], c[1];\n"
"DP4 o[HPOS].z, v[OPOS], c[2];\n"
"DP4 o[HPOS].w, v[OPOS], c[3];\n"
#endif
"END\n";
 
// if (!glutExtensionSupported("GL_NV_vertex_program")) {
// printf("Sorry, this program requires GL_NV_vertex_program\n");
// exit(1);
// }
 
glLoadProgramNV(GL_VERTEX_PROGRAM_NV, 1,
strlen(prog1),
(const GLubyte *) prog1);
assert(glIsProgramNV(1));
 
glBindProgramNV(GL_VERTEX_PROGRAM_NV, 1);
 
printf("glGetError = %x\n", (int) glGetError());
}
#endif
 
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
 
#define DEG_TO_RAD(DEG) ((DEG) * M_PI / 180.0)
 
#define TEXTURE_FILE "reflect.rgb"
 
/* Target engine speed: */
const int RPM = 100.0;
 
static int Win = 0;
 
 
/**
* Engine description.
*/
typedef struct
{
const char *Name;
int Pistons;
int Cranks;
float V_Angle;
float PistonRadius;
float PistonHeight;
float WristPinRadius;
float Throw;
float CrankPlateThickness;
float CrankPinRadius;
float CrankJournalRadius;
float CrankJournalLength;
float ConnectingRodLength;
float ConnectingRodThickness;
/* display list IDs */
GLuint CrankList;
GLuint ConnRodList;
GLuint PistonList;
GLuint BlockList;
} Engine;
 
 
typedef struct
{
float CurQuat[4];
float Distance;
/* When mouse is moving: */
GLboolean Rotating, Translating;
GLint StartX, StartY;
float StartDistance;
} ViewInfo;
 
 
typedef enum
{
LIT,
WIREFRAME,
TEXTURED
} RenderMode;
 
 
typedef struct
{
RenderMode Mode;
GLboolean Anim;
GLboolean Wireframe;
GLboolean Blend;
GLboolean Antialias;
GLboolean Texture;
GLboolean UseLists;
GLboolean DrawBox;
GLboolean ShowInfo;
GLboolean ShowBlock;
} RenderInfo;
 
 
static GLUquadric *Q;
 
static GLfloat Theta = 0.0;
 
static const GLfloat PistonColor[4] = { 1.0, 0.5, 0.5, 1.0 };
static const GLfloat ConnRodColor[4] = { 0.7, 1.0, 0.7, 1.0 };
static const GLfloat CrankshaftColor[4] = { 0.7, 0.7, 1.0, 1.0 };
static const GLfloat BlockColor[4] = {0.8, 0.8, 0.8, 0.75 };
 
static GLuint TextureObj;
static GLint WinWidth = 800, WinHeight = 500;
 
static ViewInfo View;
static RenderInfo Render;
 
void build_rotmatrix(float m[4][4], const float q[4])
{
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
m[0][3] = 0.0;
 
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
m[1][1]= 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
m[1][3] = 0.0;
 
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
m[2][3] = 0.0;
 
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
m[3][3] = 1.0;
}
 
 
#define NUM_ENGINES 3
static Engine Engines[NUM_ENGINES] =
{
{
"V-6",
6, /* Pistons */
3, /* Cranks */
90.0, /* V_Angle */
0.5, /* PistonRadius */
0.6, /* PistonHeight */
0.1, /* WristPinRadius */
0.5, /* Throw */
0.2, /* CrankPlateThickness */
0.25, /* CrankPinRadius */
0.3, /* CrankJournalRadius */
0.4, /* CrankJournalLength */
1.5, /* ConnectingRodLength */
0.1, /* ConnectingRodThickness */
0, /* CrankList */
0, /* ConnRodList */
0, /* PistonList */
0 /* BlockList */
},
{
"Inline-4",
4, /* Pistons */
4, /* Cranks */
0.0, /* V_Angle */
0.5, /* PistonRadius */
0.6, /* PistonHeight */
0.1, /* WristPinRadius */
0.5, /* Throw */
0.2, /* CrankPlateThickness */
0.25, /* CrankPinRadius */
0.3, /* CrankJournalRadius */
0.4, /* CrankJournalLength */
1.5, /* ConnectingRodLength */
0.1, /* ConnectingRodThickness */
0, /* CrankList */
0, /* ConnRodList */
0, /* PistonList */
0 /* BlockList */
},
{
"Boxer-6",
6, /* Pistons */
3, /* Cranks */
180.0,/* V_Angle */
0.5, /* PistonRadius */
0.6, /* PistonHeight */
0.1, /* WristPinRadius */
0.5, /* Throw */
0.2, /* CrankPlateThickness */
0.25, /* CrankPinRadius */
0.3, /* CrankJournalRadius */
0.4, /* CrankJournalLength */
1.5, /* ConnectingRodLength */
0.1, /* ConnectingRodThickness */
0, /* CrankList */
0, /* ConnRodList */
0, /* PistonList */
0 /* BlockList */
}
};
 
static int CurEngine = 0;
 
 
 
static void
InitViewInfo(ViewInfo *view)
{
view->Rotating = GL_FALSE;
view->Translating = GL_FALSE;
view->StartX = view->StartY = 0;
view->Distance = 12.0;
view->StartDistance = 0.0;
view->CurQuat[0] = -0.194143;
view->CurQuat[1] = 0.507848;
view->CurQuat[2] = 0.115245;
view->CurQuat[3] = 0.831335;
}
 
 
static void
InitRenderInfo(RenderInfo *render)
{
render->Mode = LIT;
render->Anim = GL_TRUE;
render->Wireframe = GL_FALSE;
render->Blend = GL_FALSE;
render->Antialias = GL_FALSE;
render->Texture = GL_FALSE;
render->DrawBox = GL_FALSE;
render->ShowInfo = GL_TRUE;
render->ShowBlock = GL_FALSE;
render->UseLists = GL_FALSE;
}
 
 
/**
* Set GL for given rendering mode.
*/
static void
SetRenderState(RenderMode mode)
{
static const GLfloat gray2[4] = { 0.2, 0.2, 0.2, 1.0 };
static const GLfloat gray4[4] = { 0.4, 0.4, 0.4, 1.0 };
 
/* defaults */
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gray2);
 
switch (mode) {
case LIT:
glEnable(GL_LIGHTING);
break;
case WIREFRAME:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glLineWidth(1.5);
break;
case TEXTURED:
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, gray4);
break;
default:
;
}
}
 
 
/**
* Animate the engine parts.
*/
void idle(void)
{
/* convert degrees per millisecond to RPM: */
const float m = 360.0 / 1000.0 / 60.0;
static GLfloat t;
t+=10;
Theta = ((int) (t * RPM * m)) % 360;
 
}
 
 
/**
* Compute piston's position along its stroke.
*/
static float
PistonStrokePosition(float throwDist, float crankAngle, float connRodLength)
{
float x = throwDist * cos(DEG_TO_RAD(crankAngle));
float y = throwDist * sin(DEG_TO_RAD(crankAngle));
float pos = y + sqrt(connRodLength * connRodLength - x * x);
return pos;
}
 
 
/**
* Compute position of nth piston along the crankshaft.
*/
static float
PistonShaftPosition(const Engine *eng, int piston)
{
const int i = piston / (eng->Pistons / eng->Cranks);
float z;
assert(piston < eng->Pistons);
z = 1.5 * eng->CrankJournalLength + eng->CrankPlateThickness
+ i * (2.0 * (eng->CrankJournalLength + eng->CrankPlateThickness));
if (eng->Pistons > eng->Cranks) {
if (piston & 1)
z += eng->ConnectingRodThickness;
else
z -= eng->ConnectingRodThickness;
}
return z;
}
 
 
/**
* Compute distance between two adjacent pistons
*/
static float
PistonSpacing(const Engine *eng)
{
const int pistonsPerCrank = eng->Pistons / eng->Cranks;
const float z0 = PistonShaftPosition(eng, 0);
const float z1 = PistonShaftPosition(eng, pistonsPerCrank);
return z1 - z0;
}
 
 
/**
* (x0, y0) = position of big end on crankshaft
* (x1, y1) = position of small end on piston
*/
static void
ComputeConnectingRodPosition(float throwDist, float crankAngle,
float connRodLength,
float *x0, float *y0, float *x1, float *y1)
{
*x0 = throwDist * cos(DEG_TO_RAD(crankAngle));
*y0 = throwDist * sin(DEG_TO_RAD(crankAngle));
*x1 = 0.0;
*y1 = PistonStrokePosition(throwDist, crankAngle, connRodLength);
}
 
 
/**
* Compute total length of the crankshaft.
*/
static float
CrankshaftLength(const Engine *eng)
{
float len = (eng->Cranks * 2 + 1) * eng->CrankJournalLength
+ 2 * eng->Cranks * eng->CrankPlateThickness;
return len;
}
 
 
/**
* Draw a piston.
* Axis of piston = Z axis. Wrist pin is centered on (0, 0, 0).
*/
static void
DrawPiston(const Engine *eng)
{
const int slices = 30, stacks = 4, loops = 4;
const float innerRadius = 0.9 * eng->PistonRadius;
const float innerHeight = eng->PistonHeight - 0.15;
const float wristPinLength = 1.8 * eng->PistonRadius;
 
assert(Q);
 
glPushMatrix();
glTranslatef(0, 0, -1.1 * eng->WristPinRadius);
 
gluQuadricOrientation(Q, GLU_INSIDE);
 
/* bottom rim */
gluDisk(Q, innerRadius, eng->PistonRadius, slices, 1/*loops*/);
 
/* inner cylinder */
gluCylinder(Q, innerRadius, innerRadius, innerHeight, slices, stacks);
 
/* inside top */
glPushMatrix();
glTranslatef(0, 0, innerHeight);
gluDisk(Q, 0, innerRadius, slices, loops);
glPopMatrix();
 
gluQuadricOrientation(Q, GLU_OUTSIDE);
 
/* outer cylinder */
gluCylinder(Q, eng->PistonRadius, eng->PistonRadius, eng->PistonHeight,
slices, stacks);
 
/* top */
glTranslatef(0, 0, eng->PistonHeight);
gluDisk(Q, 0, eng->PistonRadius, slices, loops);
 
glPopMatrix();
 
/* wrist pin */
glPushMatrix();
glTranslatef(0, 0.5 * wristPinLength, 0.0);
glRotatef(90, 1, 0, 0);
gluCylinder(Q, eng->WristPinRadius, eng->WristPinRadius, wristPinLength,
slices, stacks);
glPopMatrix();
}
 
 
/**
* Draw piston at particular position.
*/
static void
DrawPositionedPiston(const Engine *eng, float crankAngle)
{
const float pos = PistonStrokePosition(eng->Throw, crankAngle,
eng->ConnectingRodLength);
glPushMatrix();
glRotatef(-90, 1, 0, 0);
glTranslatef(0, 0, pos);
if (eng->PistonList)
glCallList(eng->PistonList);
else
DrawPiston(eng);
glPopMatrix();
}
 
 
/**
* Draw connector plate. Used for crankshaft and connecting rods.
*/
static void
DrawConnector(float length, float thickness,
float bigEndRadius, float smallEndRadius)
{
const float bigRadius = 1.2 * bigEndRadius;
const float smallRadius = 1.2 * smallEndRadius;
const float z0 = -0.5 * thickness, z1 = -z0;
GLfloat points[36][2], normals[36][2];
int i;
 
/* compute vertex locations, normals */
for (i = 0; i < 36; i++) {
const int angle = i * 10;
float x = cos(DEG_TO_RAD(angle));
float y = sin(DEG_TO_RAD(angle));
normals[i][0] = x;
normals[i][1] = y;
if (angle >= 0 && angle <= 180) {
x *= smallRadius;
y = y * smallRadius + length;
}
else {
x *= bigRadius;
y *= bigRadius;
}
points[i][0] = x;
points[i][1] = y;
}
 
/* front face */
glNormal3f(0, 0, 1);
glBegin(GL_POLYGON);
for (i = 0; i < 36; i++) {
glVertex3f(points[i][0], points[i][1], z1);
}
glEnd();
 
/* back face */
glNormal3f(0, 0, -1);
glBegin(GL_POLYGON);
for (i = 0; i < 36; i++) {
glVertex3f(points[35-i][0], points[35-i][1], z0);
}
glEnd();
 
/* edge */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= 36; i++) {
const int j = i % 36;
glNormal3f(normals[j][0], normals[j][1], 0);
glVertex3f(points[j][0], points[j][1], z1);
glVertex3f(points[j][0], points[j][1], z0);
}
glEnd();
}
 
 
/**
* Draw a crankshaft. Shaft lies along +Z axis, starting at zero.
*/
static void
DrawCrankshaft(const Engine *eng)
{
const int slices = 20, stacks = 2;
const int n = eng->Cranks * 4 + 1;
const float phiStep = 360 / eng->Cranks;
float phi = -90.0;
int i;
float z = 0.0;
 
for (i = 0; i < n; i++) {
glPushMatrix();
glTranslatef(0, 0, z);
if (i & 1) {
/* draw a crank plate */
glRotatef(phi, 0, 0, 1);
glTranslatef(0, 0, 0.5 * eng->CrankPlateThickness);
DrawConnector(eng->Throw, eng->CrankPlateThickness,
eng->CrankJournalRadius, eng->CrankPinRadius);
z += 0.2;
if (i % 4 == 3)
phi += phiStep;
}
else if (i % 4 == 0) {
/* draw crank journal segment */
gluCylinder(Q, eng->CrankJournalRadius, eng->CrankJournalRadius,
eng->CrankJournalLength, slices, stacks);
z += eng->CrankJournalLength;
}
else if (i % 4 == 2) {
/* draw crank pin segment */
glRotatef(phi, 0, 0, 1);
glTranslatef(0, eng->Throw, 0);
gluCylinder(Q, eng->CrankPinRadius, eng->CrankPinRadius,
eng->CrankJournalLength, slices, stacks);
z += eng->CrankJournalLength;
}
glPopMatrix();
}
}
 
 
/**
* Draw crankshaft at a particular rotation.
* \param crankAngle current crankshaft rotation, in radians
*/
static void
DrawPositionedCrankshaft(const Engine *eng, float crankAngle)
{
glPushMatrix();
glRotatef(crankAngle, 0, 0, 1);
if (eng->CrankList)
glCallList(eng->CrankList);
else
DrawCrankshaft(eng);
glPopMatrix();
}
 
 
/**
* Draw a connecting rod at particular position.
* \param eng description of connecting rod to draw
* \param crankAngle current crankshaft rotation, in radians
*/
static void
DrawPositionedConnectingRod(const Engine *eng, float crankAngle)
{
float x0, y0, x1, y1;
float d, phi;
 
ComputeConnectingRodPosition(eng->Throw, crankAngle,
eng->ConnectingRodLength,
&x0, &y0, &x1, &y1);
d = sqrt(eng->ConnectingRodLength * eng->ConnectingRodLength - x0 * x0);
phi = atan(x0 / d) * 180.0 / M_PI;
 
glPushMatrix();
glTranslatef(x0, y0, 0);
glRotatef(phi, 0, 0, 1);
if (eng->ConnRodList)
glCallList(eng->ConnRodList);
else
DrawConnector(eng->ConnectingRodLength, eng->ConnectingRodThickness,
eng->CrankPinRadius, eng->WristPinRadius);
glPopMatrix();
}
 
 
/**
* Draw a square with a hole in middle.
*/
static void
SquareWithHole(float squareSize, float holeRadius)
{
int i;
glBegin(GL_QUAD_STRIP);
glNormal3f(0, 0, 1);
for (i = 0; i <= 360; i += 5) {
const float x1 = holeRadius * cos(DEG_TO_RAD(i));
const float y1 = holeRadius * sin(DEG_TO_RAD(i));
float x2 = 0.0F, y2 = 0.0F;
if (i > 315 || i <= 45) {
x2 = squareSize;
y2 = squareSize * tan(DEG_TO_RAD(i));
}
else if (i > 45 && i <= 135) {
x2 = -squareSize * tan(DEG_TO_RAD(i - 90));
y2 = squareSize;
}
else if (i > 135 && i <= 225) {
x2 = -squareSize;
y2 = -squareSize * tan(DEG_TO_RAD(i-180));
}
else if (i > 225 && i <= 315) {
x2 = squareSize * tan(DEG_TO_RAD(i - 270));
y2 = -squareSize;
}
glVertex2f(x1, y1); /* inner circle */
glVertex2f(x2, y2); /* outer square */
}
glEnd();
}
 
 
/**
* Draw block with hole through middle.
* Hole is centered on Z axis.
* Bottom of block is at z=0, top of block is at z = blockHeight.
* index is in [0, count - 1] to determine which block faces are drawn.
*/
static void
DrawBlockWithHole(float blockSize, float blockHeight, float holeRadius,
int index, int count)
{
const int slices = 30, stacks = 4;
const float x = blockSize;
const float y = blockSize;
const float z0 = 0;
const float z1 = blockHeight;
 
assert(index < count);
assert(Q);
gluQuadricOrientation(Q, GLU_INSIDE);
 
glBegin(GL_QUADS);
/* +X face */
glNormal3f(1, 0, 0);
glVertex3f( x, -y, z0);
glVertex3f( x, y, z0);
glVertex3f( x, y, z1);
glVertex3f( x, -y, z1);
/* -X face */
glNormal3f(-1, 0, 0);
glVertex3f(-x, -y, z1);
glVertex3f(-x, y, z1);
glVertex3f(-x, y, z0);
glVertex3f(-x, -y, z0);
if (index == 0) {
/* +Y face */
glNormal3f(0, 1, 0);
glVertex3f(-x, y, z1);
glVertex3f( x, y, z1);
glVertex3f( x, y, z0);
glVertex3f(-x, y, z0);
}
if (index == count - 1) {
/* -Y face */
glNormal3f(0, -1, 0);
glVertex3f(-x, -y, z0);
glVertex3f( x, -y, z0);
glVertex3f( x, -y, z1);
glVertex3f(-x, -y, z1);
}
glEnd();
 
/* cylinder / hole */
gluCylinder(Q, holeRadius, holeRadius, blockHeight, slices, stacks);
 
/* face at z0 */
glPushMatrix();
glRotatef(180, 1, 0, 0);
SquareWithHole(blockSize, holeRadius);
glPopMatrix();
 
/* face at z1 */
glTranslatef(0, 0, z1);
SquareWithHole(blockSize, holeRadius);
 
gluQuadricOrientation(Q, GLU_OUTSIDE);
}
 
 
/**
* Draw the engine block.
*/
static void
DrawEngineBlock(const Engine *eng)
{
const float blockHeight = eng->Throw + 1.5 * eng->PistonHeight;
const float cylRadius = 1.01 * eng->PistonRadius;
const float blockSize = 0.5 * PistonSpacing(eng);
const int pistonsPerCrank = eng->Pistons / eng->Cranks;
int i;
 
for (i = 0; i < eng->Pistons; i++) {
const float z = PistonShaftPosition(eng, i);
const int crank = i / pistonsPerCrank;
int k;
 
glPushMatrix();
glTranslatef(0, 0, z);
 
/* additional rotation for kth piston per crank */
k = i % pistonsPerCrank;
glRotatef(k * -eng->V_Angle, 0, 0, 1);
 
/* the block */
glRotatef(-90, 1, 0, 0);
glTranslatef(0, 0, eng->Throw * 2);
DrawBlockWithHole(blockSize, blockHeight, cylRadius,
crank, eng->Cranks);
glPopMatrix();
}
}
 
 
/**
* Generate display lists for engine parts.
*/
static void
GenerateDisplayLists(Engine *eng)
{
eng->CrankList = glGenLists(1);
glNewList(eng->CrankList, GL_COMPILE);
DrawCrankshaft(eng);
glEndList();
 
eng->ConnRodList = glGenLists(1);
glNewList(eng->ConnRodList, GL_COMPILE);
DrawConnector(eng->ConnectingRodLength, eng->ConnectingRodThickness,
eng->CrankPinRadius, eng->WristPinRadius);
glEndList();
 
eng->PistonList = glGenLists(1);
glNewList(eng->PistonList, GL_COMPILE);
DrawPiston(eng);
glEndList();
 
eng->BlockList = glGenLists(1);
glNewList(eng->BlockList, GL_COMPILE);
DrawEngineBlock(eng);
glEndList();
}
 
 
/**
* Free engine display lists (render with immediate mode).
*/
static void
FreeDisplayLists(Engine *eng)
{
glDeleteLists(eng->CrankList, 1);
eng->CrankList = 0;
glDeleteLists(eng->ConnRodList, 1);
eng->ConnRodList = 0;
glDeleteLists(eng->PistonList, 1);
eng->PistonList = 0;
glDeleteLists(eng->BlockList, 1);
eng->BlockList = 0;
}
 
 
/**
* Draw complete engine.
* \param eng description of engine to draw
* \param crankAngle current crankshaft angle, in radians
*/
static void
DrawEngine(const Engine *eng, float crankAngle)
{
const float crankDelta = 360.0 / eng->Cranks;
const float crankLen = CrankshaftLength(eng);
const int pistonsPerCrank = eng->Pistons / eng->Cranks;
int i;
 
glPushMatrix();
glRotatef(eng->V_Angle * 0.5, 0, 0, 1);
glTranslatef(0, 0, -0.5 * crankLen);
 
/* crankshaft */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, CrankshaftColor);
glColor4fv(CrankshaftColor);
DrawPositionedCrankshaft(eng, crankAngle);
 
for (i = 0; i < eng->Pistons; i++) {
const float z = PistonShaftPosition(eng, i);
const int crank = i / pistonsPerCrank;
float rot = crankAngle + crank * crankDelta;
int k;
 
glPushMatrix();
glTranslatef(0, 0, z);
 
/* additional rotation for kth piston per crank */
k = i % pistonsPerCrank;
glRotatef(k * -eng->V_Angle, 0, 0, 1);
rot += k * eng->V_Angle;
 
/* piston */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, PistonColor);
glColor4fv(PistonColor);
DrawPositionedPiston(eng, rot);
 
/* connecting rod */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ConnRodColor);
glColor4fv(ConnRodColor);
DrawPositionedConnectingRod(eng, rot);
glPopMatrix();
}
 
if (Render.ShowBlock) {
const GLboolean blend = glIsEnabled(GL_BLEND);
 
glDepthMask(GL_FALSE);
if (!blend) {
glEnable(GL_BLEND);
}
glEnable(GL_CULL_FACE);
 
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, BlockColor);
glColor4fv(BlockColor);
if (eng->CrankList)
glCallList(eng->BlockList);
else
DrawEngineBlock(eng);
 
glDisable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
if (!blend) {
glDisable(GL_BLEND);
}
}
 
glPopMatrix();
}
 
 
static void
DrawBox(void)
{
const float xmin = -3.0, xmax = 3.0;
const float ymin = -1.0, ymax = 3.0;
const float zmin = -4.0, zmax = 4.0;
const float step = 0.5;
const float d = 0.01;
float x, y, z;
GLboolean lit = glIsEnabled(GL_LIGHTING);
GLboolean tex = glIsEnabled(GL_TEXTURE_2D);
 
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glLineWidth(1.0);
 
glColor3f(1, 1, 1);
 
/* Z min */
glBegin(GL_LINES);
for (x = xmin; x <= xmax; x += step) {
glVertex3f(x, ymin, zmin);
glVertex3f(x, ymax, zmin);
}
glEnd();
glBegin(GL_LINES);
for (y = ymin; y <= ymax; y += step) {
glVertex3f(xmin, y, zmin);
glVertex3f(xmax, y, zmin);
}
glEnd();
 
/* Y min */
glBegin(GL_LINES);
for (x = xmin; x <= xmax; x += step) {
glVertex3f(x, ymin, zmin);
glVertex3f(x, ymin, zmax);
}
glEnd();
glBegin(GL_LINES);
for (z = zmin; z <= zmax; z += step) {
glVertex3f(xmin, ymin, z);
glVertex3f(xmax, ymin, z);
}
glEnd();
 
/* X min */
glBegin(GL_LINES);
for (y = ymin; y <= ymax; y += step) {
glVertex3f(xmin, y, zmin);
glVertex3f(xmin, y, zmax);
}
glEnd();
glBegin(GL_LINES);
for (z = zmin; z <= zmax; z += step) {
glVertex3f(xmin, ymin, z);
glVertex3f(xmin, ymax, z);
}
glEnd();
 
glColor3f(0.4, 0.4, 0.6);
glBegin(GL_QUADS);
/* xmin */
glVertex3f(xmin-d, ymin, zmin);
glVertex3f(xmin-d, ymax, zmin);
glVertex3f(xmin-d, ymax, zmax);
glVertex3f(xmin-d, ymin, zmax);
/* ymin */
glVertex3f(xmin, ymin-d, zmin);
glVertex3f(xmax, ymin-d, zmin);
glVertex3f(xmax, ymin-d, zmax);
glVertex3f(xmin, ymin-d, zmax);
/* zmin */
glVertex3f(xmin, ymin, zmin-d);
glVertex3f(xmax, ymin, zmin-d);
glVertex3f(xmax, ymax, zmin-d);
glVertex3f(xmin, ymax, zmin-d);
glEnd();
 
if (lit)
glEnable(GL_LIGHTING);
if (tex)
glEnable(GL_TEXTURE_2D);
}
 
/*
static void
PrintString(const char *s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
s++;
}
}
*/
 
 
void draw(void)
{
int fps;
GLfloat rot[4][4];
 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
glPushMatrix();
 
glTranslatef(0.0, 0.0, -View.Distance);
build_rotmatrix(rot, View.CurQuat);
glMultMatrixf(&rot[0][0]);
 
glPushMatrix();
glTranslatef(0, -0.75, 0);
if (Render.DrawBox)
DrawBox();
DrawEngine(Engines + CurEngine, Theta);
glPopMatrix();
 
glPopMatrix();
 
}
 
 
/**
* Handle window resize.
*/
void reshape(int width, int height)
{
float ar = (float) width / height;
float s = 0.5;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar * s, ar * s, -s, s, 2.0, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
WinWidth = width;
WinHeight = height;
}
 
#if 0
/**
* Handle mouse button.
*/
static void
Mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.Rotating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Rotating = GL_FALSE;
}
}
else if (button == GLUT_MIDDLE_BUTTON) {
if (state == GLUT_DOWN) {
View.StartX = x;
View.StartY = y;
View.StartDistance = View.Distance;
View.Translating = GL_TRUE;
}
else if (state == GLUT_UP) {
View.Translating = GL_FALSE;
}
}
}
 
 
/**
* Handle mouse motion
*/
static void
Motion(int x, int y)
{
int i;
if (View.Rotating) {
float x0 = (2.0 * View.StartX - WinWidth) / WinWidth;
float y0 = (WinHeight - 2.0 * View.StartY) / WinHeight;
float x1 = (2.0 * x - WinWidth) / WinWidth;
float y1 = (WinHeight - 2.0 * y) / WinHeight;
float q[4];
 
trackball(q, x0, y0, x1, y1);
View.StartX = x;
View.StartY = y;
for (i = 0; i < 1; i++)
add_quats(q, View.CurQuat, View.CurQuat);
}
else if (View.Translating) {
float dz = 0.01 * (y - View.StartY);
View.Distance = View.StartDistance + dz;
}
}
#endif
 
/**
** Menu Callbacks
**/
 
static void
OptChangeEngine(void)
{
CurEngine = (CurEngine + 1) % NUM_ENGINES;
}
 
static void
OptRenderMode(void)
{
Render.Mode++;
if (Render.Mode > TEXTURED)
Render.Mode = 0;
SetRenderState(Render.Mode);
}
 
static void
OptDisplayLists(void)
{
int i;
Render.UseLists = !Render.UseLists;
if (Render.UseLists) {
for (i = 0; i < NUM_ENGINES; i++) {
GenerateDisplayLists(Engines + i);
}
}
else {
for (i = 0; i < NUM_ENGINES; i++) {
FreeDisplayLists(Engines + i);
}
}
}
 
static void
OptShowBlock(void)
{
Render.ShowBlock = !Render.ShowBlock;
}
 
static void
OptShowInfo(void)
{
Render.ShowInfo = !Render.ShowInfo;
}
 
static void
OptShowBox(void)
{
Render.DrawBox = !Render.DrawBox;
}
 
static void
OptRotate(void)
{
Theta += 5.0;
}
 
/**
* Define menu entries (w/ keyboard shortcuts)
*/
 
typedef struct
{
const char *Text;
const char Key;
void (*Function)(void);
} MenuInfo;
 
static const MenuInfo MenuItems[] = {
{ "Change Engine", 'e', OptChangeEngine },
{ "Rendering Style", 'm', OptRenderMode },
{ "Display Lists", 'd', OptDisplayLists },
{ "Show Block", 98, OptShowBlock }, /* b */
{ "Show Box", 'x', OptShowBox },
{ NULL, 'r', OptRotate },
{ NULL, 0, NULL }
};
 
 
/**
* Handle keyboard event.
*/
void Key(unsigned char key, int x, int y)
{
int i;
(void) x; (void) y;
 
for (i = 0; MenuItems[i].Key; i++)
{
if (MenuItems[i].Key == key)
{
MenuItems[i].Function();
break;
}
}
}
 
static void LoadTexture(void)
{
GLboolean convolve = GL_FALSE;
 
glGenTextures(1, &TextureObj);
glBindTexture(GL_TEXTURE_2D, TextureObj);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
 
if (convolve) {
#define FILTER_SIZE 7
/* use convolution to blur the texture to simulate a dull finish
* on the object.
*/
GLubyte *img;
GLenum format;
GLint w, h;
GLfloat filter[FILTER_SIZE][FILTER_SIZE][4];
 
for (h = 0; h < FILTER_SIZE; h++) {
for (w = 0; w < FILTER_SIZE; w++) {
const GLfloat k = 1.0 / (FILTER_SIZE * FILTER_SIZE);
filter[h][w][0] = k;
filter[h][w][1] = k;
filter[h][w][2] = k;
filter[h][w][3] = k;
}
}
 
glEnable(GL_CONVOLUTION_2D);
glConvolutionParameteri(GL_CONVOLUTION_2D,
GL_CONVOLUTION_BORDER_MODE, GL_CONSTANT_BORDER);
glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_RGBA,
FILTER_SIZE, FILTER_SIZE,
GL_RGBA, GL_FLOAT, filter);
 
img = LoadRGBImage(TEXTURE_FILE, &w, &h, &format);
if (!img) {
printf("Error: couldn't load texture image file %s\n", TEXTURE_FILE);
exit(1);
}
 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
format, GL_UNSIGNED_BYTE, img);
free(img);
}
else {
if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
printf("Error: couldn't load texture image file %s\n", TEXTURE_FILE);
exit(1);
}
}
}
 
 
void init(void)
{
const GLfloat lightColor[4] = { 0.7, 0.7, 0.7, 1.0 };
const GLfloat specular[4] = { 0.8, 0.8, 0.8, 1.0 };
const GLfloat backColor[4] = { 1, 1, 0, 0 };
 
Q = gluNewQuadric();
gluQuadricNormals(Q, GLU_SMOOTH);
 
LoadTexture();
 
glClearColor(0.3, 0.3, 0.3, 0.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
glMaterialf(GL_FRONT, GL_SHININESS, 40);
glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
glEnable(GL_NORMALIZE);
 
glMaterialfv(GL_BACK, GL_DIFFUSE, backColor);
#if 0
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
#endif
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
InitViewInfo(&View);
InitRenderInfo(&Render);
}
 
int atexit(void (*func)(void))
{
return 0;
};
 
/*
#define GL_NO_ERROR 0x0
#define GL_INVALID_ENUM 0x0500
#define GL_INVALID_VALUE 0x0501
#define GL_INVALID_OPERATION 0x0502
#define GL_STACK_OVERFLOW 0x0503
#define GL_STACK_UNDERFLOW 0x0504
#define GL_OUT_OF_MEMORY 0x0505
*/
 
 
 
/contrib/sdk/samples/Mesa/gears.c
0,0 → 1,253
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/osmesa.h"
#include "GL/glu.h"
 
#define XK_Left 176
#define XK_Right 179
#define XK_Up 178
#define XK_Down 177
 
extern GLfloat view_rotx, view_roty, view_rotz;
GLint gear1, gear2, gear3;
extern GLfloat angle;
 
static void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
GLint teeth, GLfloat tooth_depth)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
 
r0 = inner_radius;
r1 = outer_radius - tooth_depth / 2.0;
r2 = outer_radius + tooth_depth / 2.0;
 
da = 2.0 * M_PI / teeth / 4.0;
 
glShadeModel(GL_FLAT);
 
glNormal3f(0.0, 0.0, 1.0);
 
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
if (i < teeth) {
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
width * 0.5);
}
}
glEnd();
 
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
 
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
width * 0.5);
}
glEnd();
 
glNormal3f(0.0, 0.0, -1.0);
 
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
if (i < teeth) {
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
-width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
}
}
glEnd();
 
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / teeth / 4.0;
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
 
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
-width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
-width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
}
glEnd();
 
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
 
glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
-width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
-width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
 
glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
 
glEnd();
 
glShadeModel(GL_SMOOTH);
 
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= teeth; i++) {
angle = i * 2.0 * M_PI / teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
}
glEnd();
}
 
void Draw(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
glPushMatrix();
glRotatef(view_rotx, 1.0, 0.0, 0.0);
glRotatef(view_roty, 0.0, 1.0, 0.0);
glRotatef(view_rotz, 0.0, 0.0, 1.0);
 
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
glCallList(gear1);
glPopMatrix();
 
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
glCallList(gear2);
glPopMatrix();
 
glPushMatrix();
glTranslatef(-3.1, 4.2, 0.0);
glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
glCallList(gear3);
glPopMatrix();
 
glPopMatrix();
}
 
 
/* new window size or exposure */
void Reshape(int width, int height)
{
glViewport(0, 0, (GLint) width, (GLint) height);
 
GLfloat h = (GLfloat) height / (GLfloat) width;
 
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
 
 
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -40.0);
}
 
 
void Init(void)
{
static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
 
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
 
/* make the gears */
gear1 = glGenLists(1);
glNewList(gear1, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
gear(1.0, 4.0, 1.0, 20, 0.7);
glEndList();
 
gear2 = glGenLists(1);
glNewList(gear2, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
gear(0.5, 2.0, 2.0, 10, 0.7);
glEndList();
 
gear3 = glGenLists(1);
glNewList(gear3, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
gear(1.3, 2.0, 0.5, 10, 0.7);
glEndList();
 
glEnable(GL_NORMALIZE);
}
 
void Key(unsigned char code, int x, int y)
{
int i;
(void) x; (void) y;
 
if (code == XK_Left) {
view_roty += 5.0;
}
else if (code == XK_Right) {
view_roty -= 5.0;
}
else if (code == XK_Up) {
view_rotx += 5.0;
}
else if (code == XK_Down) {
view_rotx -= 5.0;
}
};
 
void Idle(void)
{
angle += 70.0 * 0.05; /* 70 degrees per second */
if (angle > 3600.0)
angle -= 3600.0;
}
 
 
/contrib/sdk/samples/Mesa/gluint.h
0,0 → 1,48
/*
* 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.
*/
 
#ifndef __gluint_h__
#define __gluint_h__
 
extern const unsigned char *__gluNURBSErrorString( int errnum );
 
extern const unsigned char *__gluTessErrorString( int errnum );
 
#ifdef _EXTENSIONS_
#define COS cosf
#define SIN sinf
#define SQRT sqrtf
#else
#define COS cos
#define SIN sin
#define SQRT sqrt
#endif
 
#endif /* __gluint_h__ */
/contrib/sdk/samples/Mesa/gluos.h
0,0 → 1,72
/*
** gluos.h - operating system dependencies for GLU
**
*/
#ifdef __VMS
#ifdef __cplusplus
#pragma message disable nocordel
#pragma message disable codeunreachable
#pragma message disable codcauunr
#endif
#endif
 
#ifdef __WATCOMC__
/* Disable *lots* of warnings to get a clean build. I can't be bothered fixing the
* code at the moment, as it is pretty ugly.
*/
#pragma warning 7 10
#pragma warning 13 10
#pragma warning 14 10
#pragma warning 367 10
#pragma warning 379 10
#pragma warning 726 10
#pragma warning 836 10
#endif
 
#ifdef BUILD_FOR_SNAP
 
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
 
#elif defined(_WIN32)
 
#include <stdlib.h> /* For _MAX_PATH definition */
#include <stdio.h>
#include <malloc.h>
 
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOIME
#define NOMINMAX
 
#define _WIN32_WINNT 0x0400
#ifndef STRICT
#define STRICT 1
#endif
 
#include <windows.h>
 
/* Disable warnings */
#pragma warning(disable : 4101)
#pragma warning(disable : 4244)
#pragma warning(disable : 4761)
 
#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1300
#pragma comment(linker, "/OPT:NOWIN98")
#endif
 
#elif defined(__OS2__)
 
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
#define WINGDIAPI
 
#else
 
/* Disable Microsoft-specific keywords */
//#define GLAPIENTRY
//#define WINGDIAPI
 
#endif
/contrib/sdk/samples/Mesa/glut_shapes.c
0,0 → 1,610
 
/* Copyright (c) Mark J. Kilgard, 1994, 1997. */
 
/**
(c) Copyright 1993, Silicon Graphics, Inc.
 
ALL RIGHTS RESERVED
 
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that
both the copyright notice and this permission notice appear in
supporting documentation, and that the name of Silicon
Graphics, Inc. not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission.
 
THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
PERFORMANCE OF THIS SOFTWARE.
 
US Government Users Restricted Rights
 
Use, duplication, or disclosure by the Government is subject to
restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
(c)(1)(ii) of the Rights in Technical Data and Computer
Software clause at DFARS 252.227-7013 and/or in similar or
successor clauses in the FAR or the DOD or NASA FAR
Supplement. Unpublished-- rights reserved under the copyright
laws of the United States. Contractor/manufacturer is Silicon
Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
94039-7311.
 
OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
 
#include <math.h>
#include "gluos.h"
#include "gluint.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
 
//#include "glutint.h"
#define GLUTAPIENTRY
 
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
 
static GLUquadricObj *quadObj;
 
#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
 
 
static void
initQuadObj(void)
{
quadObj = gluNewQuadric();
if (!quadObj)
{
printf("%s: out of memory.\n", __FUNCTION__);
abort();
};
// __glutFatalError("out of memory.");
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_LINE);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluSphere(quadObj, radius, slices, stacks);
}
 
void GLUTAPIENTRY
glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_FILL);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluSphere(quadObj, radius, slices, stacks);
}
 
void GLUTAPIENTRY
glutWireCone(GLdouble base, GLdouble height,
GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_LINE);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
 
void GLUTAPIENTRY
glutSolidCone(GLdouble base, GLdouble height,
GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_FILL);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
 
/* ENDCENTRY */
 
static void
drawBox(GLfloat size, GLenum type)
{
static GLfloat n[6][3] =
{
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
static GLint faces[6][4] =
{
{0, 1, 2, 3},
{3, 2, 6, 7},
{7, 6, 5, 4},
{4, 5, 1, 0},
{5, 6, 2, 1},
{7, 4, 0, 3}
};
GLfloat v[8][3];
GLint i;
 
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
 
for (i = 5; i >= 0; i--) {
glBegin(type);
glNormal3fv(&n[i][0]);
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireCube(GLdouble size)
{
drawBox(size, GL_LINE_LOOP);
}
 
void GLUTAPIENTRY
glutSolidCube(GLdouble size)
{
drawBox(size, GL_QUADS);
}
 
/* ENDCENTRY */
 
static void
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
{
int i, j;
GLfloat theta, phi, theta1;
GLfloat cosTheta, sinTheta;
GLfloat cosTheta1, sinTheta1;
GLfloat ringDelta, sideDelta;
 
ringDelta = 2.0 * M_PI / rings;
sideDelta = 2.0 * M_PI / nsides;
 
theta = 0.0;
cosTheta = 1.0;
sinTheta = 0.0;
for (i = rings - 1; i >= 0; i--) {
theta1 = theta + ringDelta;
cosTheta1 = cos(theta1);
sinTheta1 = sin(theta1);
glBegin(GL_QUAD_STRIP);
phi = 0.0;
for (j = nsides; j >= 0; j--) {
GLfloat cosPhi, sinPhi, dist;
 
phi += sideDelta;
cosPhi = cos(phi);
sinPhi = sin(phi);
dist = R + r * cosPhi;
 
glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
}
glEnd();
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;
}
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings)
{
glPushAttrib(GL_POLYGON_BIT);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
doughnut(innerRadius, outerRadius, nsides, rings);
glPopAttrib();
}
 
void GLUTAPIENTRY
glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings)
{
doughnut(innerRadius, outerRadius, nsides, rings);
}
 
/* ENDCENTRY */
 
static GLfloat dodec[20][3];
 
static void
initDodecahedron(void)
{
GLfloat alpha, beta;
 
alpha = sqrt(2.0 / (3.0 + sqrt(5.0)));
beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) -
2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0))));
/* *INDENT-OFF* */
dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
/* *INDENT-ON* */
 
}
 
#define DIFF3(_a,_b,_c) { \
(_c)[0] = (_a)[0] - (_b)[0]; \
(_c)[1] = (_a)[1] - (_b)[1]; \
(_c)[2] = (_a)[2] - (_b)[2]; \
}
 
static void
crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3])
{
GLfloat p[3]; /* in case prod == v1 or v2 */
 
p[0] = v1[1] * v2[2] - v2[1] * v1[2];
p[1] = v1[2] * v2[0] - v2[2] * v1[0];
p[2] = v1[0] * v2[1] - v2[0] * v1[1];
prod[0] = p[0];
prod[1] = p[1];
prod[2] = p[2];
}
 
static void
normalize(GLfloat v[3])
{
GLfloat d;
 
d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if (d == 0.0) {
// __glutWarning("normalize: zero length vector");
v[0] = d = 1.0;
}
d = 1 / d;
v[0] *= d;
v[1] *= d;
v[2] *= d;
}
 
static void
pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
{
GLfloat n0[3], d1[3], d2[3];
 
DIFF3(dodec[a], dodec[b], d1);
DIFF3(dodec[b], dodec[c], d2);
crossprod(d1, d2, n0);
normalize(n0);
 
glBegin(shadeType);
glNormal3fv(n0);
glVertex3fv(&dodec[a][0]);
glVertex3fv(&dodec[b][0]);
glVertex3fv(&dodec[c][0]);
glVertex3fv(&dodec[d][0]);
glVertex3fv(&dodec[e][0]);
glEnd();
}
 
static void
dodecahedron(GLenum type)
{
static int inited = 0;
 
if (inited == 0) {
inited = 1;
initDodecahedron();
}
pentagon(0, 1, 9, 16, 5, type);
pentagon(1, 0, 3, 18, 7, type);
pentagon(1, 7, 11, 10, 9, type);
pentagon(11, 7, 18, 19, 6, type);
pentagon(8, 17, 16, 9, 10, type);
pentagon(2, 14, 15, 6, 19, type);
pentagon(2, 13, 12, 4, 14, type);
pentagon(2, 19, 18, 3, 13, type);
pentagon(3, 0, 5, 12, 13, type);
pentagon(6, 15, 8, 10, 11, type);
pentagon(4, 17, 8, 15, 14, type);
pentagon(4, 12, 5, 16, 17, type);
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireDodecahedron(void)
{
dodecahedron(GL_LINE_LOOP);
}
 
void GLUTAPIENTRY
glutSolidDodecahedron(void)
{
dodecahedron(GL_TRIANGLE_FAN);
}
 
/* ENDCENTRY */
 
static void
recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
GLenum shadeType)
{
GLfloat q0[3], q1[3];
 
DIFF3(n1, n2, q0);
DIFF3(n2, n3, q1);
crossprod(q0, q1, q1);
normalize(q1);
 
glBegin(shadeType);
glNormal3fv(q1);
glVertex3fv(n1);
glVertex3fv(n2);
glVertex3fv(n3);
glEnd();
}
 
static void
subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2,
GLenum shadeType)
{
int depth;
GLfloat w0[3], w1[3], w2[3];
GLfloat l;
int i, j, k, n;
 
depth = 1;
for (i = 0; i < depth; i++) {
for (j = 0; i + j < depth; j++) {
k = depth - i - j;
for (n = 0; n < 3; n++) {
w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
/ depth;
w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
/ depth;
}
l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
w0[0] /= l;
w0[1] /= l;
w0[2] /= l;
l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
w1[0] /= l;
w1[1] /= l;
w1[2] /= l;
l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
w2[0] /= l;
w2[1] /= l;
w2[2] /= l;
recorditem(w1, w0, w2, shadeType);
}
}
}
 
static void
drawtriangle(int i, GLfloat data[][3], int ndx[][3],
GLenum shadeType)
{
GLfloat *x0, *x1, *x2;
 
x0 = data[ndx[i][0]];
x1 = data[ndx[i][1]];
x2 = data[ndx[i][2]];
subdivide(x0, x1, x2, shadeType);
}
 
/* octahedron data: The octahedron produced is centered at the
origin and has radius 1.0 */
static GLfloat odata[6][3] =
{
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
 
static int ondex[8][3] =
{
{0, 4, 2},
{1, 2, 4},
{0, 3, 4},
{1, 4, 3},
{0, 2, 5},
{1, 5, 2},
{0, 5, 3},
{1, 3, 5}
};
 
static void
octahedron(GLenum shadeType)
{
int i;
 
for (i = 7; i >= 0; i--) {
drawtriangle(i, odata, ondex, shadeType);
}
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireOctahedron(void)
{
octahedron(GL_LINE_LOOP);
}
 
void GLUTAPIENTRY
glutSolidOctahedron(void)
{
octahedron(GL_TRIANGLES);
}
 
/* ENDCENTRY */
 
/* icosahedron data: These numbers are rigged to make an
icosahedron of radius 1.0 */
 
#define X .525731112119133606
#define Z .850650808352039932
 
static GLfloat idata[12][3] =
{
{-X, 0, Z},
{X, 0, Z},
{-X, 0, -Z},
{X, 0, -Z},
{0, Z, X},
{0, Z, -X},
{0, -Z, X},
{0, -Z, -X},
{Z, X, 0},
{-Z, X, 0},
{Z, -X, 0},
{-Z, -X, 0}
};
 
static int index[20][3] =
{
{0, 4, 1},
{0, 9, 4},
{9, 5, 4},
{4, 5, 8},
{4, 8, 1},
{8, 10, 1},
{8, 3, 10},
{5, 3, 8},
{5, 2, 3},
{2, 7, 3},
{7, 10, 3},
{7, 6, 10},
{7, 11, 6},
{11, 0, 6},
{0, 1, 6},
{6, 1, 10},
{9, 0, 11},
{9, 11, 2},
{9, 2, 5},
{7, 2, 11},
};
 
static void
icosahedron(GLenum shadeType)
{
int i;
 
for (i = 19; i >= 0; i--) {
drawtriangle(i, idata, index, shadeType);
}
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireIcosahedron(void)
{
icosahedron(GL_LINE_LOOP);
}
 
void GLUTAPIENTRY
glutSolidIcosahedron(void)
{
icosahedron(GL_TRIANGLES);
}
 
/* ENDCENTRY */
 
/* tetrahedron data: */
 
#define T 1.73205080756887729
 
static GLfloat tdata[4][3] =
{
{T, T, T},
{T, -T, -T},
{-T, T, -T},
{-T, -T, T}
};
 
static int tndex[4][3] =
{
{0, 1, 3},
{2, 1, 0},
{3, 2, 0},
{1, 2, 3}
};
 
static void
tetrahedron(GLenum shadeType)
{
int i;
 
for (i = 3; i >= 0; i--)
drawtriangle(i, tdata, tndex, shadeType);
}
 
/* CENTRY */
void GLUTAPIENTRY
glutWireTetrahedron(void)
{
tetrahedron(GL_LINE_LOOP);
}
 
void GLUTAPIENTRY
glutSolidTetrahedron(void)
{
tetrahedron(GL_TRIANGLES);
}
 
/* ENDCENTRY */
/contrib/sdk/samples/Mesa/glutint.h
0,0 → 1,798
#ifndef __glutint_h__
#define __glutint_h__
 
/* Copyright (c) Mark J. Kilgard, 1994, 1997, 1998. */
 
/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
 
#ifdef __VMS
#include <GL/vms_x_fix.h>
#endif
 
#if defined(__CYGWIN32__)
#include <sys/time.h>
#endif
 
#define SUPPORT_FORTRAN /* With GLUT 3.7, everyone supports Fortran. */
 
#if defined(_WIN32)
#include "glutwin32.h"
#else
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define GLX_GLXEXT_PROTOTYPES
#include <GL/glx.h>
#endif
 
#ifndef GLUT_BUILDING_LIB
#define GLUT_BUILDING_LIB /* Building the GLUT library itself. */
#endif
 
#include <GL/glut.h>
 
#ifndef _WIN32
/* added by BrianP: */
#ifndef APIENTRY
#define APIENTRY GLAPIENTRY
#endif
#define __cdecl GLAPIENTRY
#define CDECL GLAPIENTRY
#endif
 
/* GLUT_BUILDING_LIB is used by <GL/glut.h> to 1) not #pragma link
with the GLUT library, and 2) avoid the Win32 atexit hack. */
 
#ifdef SUPPORT_FORTRAN
#include <GL/glutf90.h>
#endif
 
#ifdef __vms
#if ( __VMS_VER < 70000000 )
#define OLD_VMS
struct timeval6 {
__int64 val;
};
extern int sys$gettim(struct timeval6 *);
#else
#include <time.h>
#endif
#else
#include <sys/types.h>
#if !defined(_WIN32) || defined(__CYGWIN32__)
#include <sys/time.h>
#else
#include <winsock.h>
#endif
#endif
#if defined(__vms) && ( __VMS_VER < 70000000 )
 
/* For VMS6.2 or lower :
One TICK on VMS is 100 nanoseconds; 0.1 microseconds or
0.0001 milliseconds. This means that there are 0.01
ticks/ns, 10 ticks/us, 10,000 ticks/ms and 10,000,000
ticks/second. */
 
#define TICKS_PER_MILLISECOND 10000
#define TICKS_PER_SECOND 10000000
 
#define GETTIMEOFDAY(_x) (void) sys$gettim (_x);
 
#define ADD_TIME(dest, src1, src2) { \
(dest).val = (src1).val + (src2).val; \
}
 
#define TIMEDELTA(dest, src1, src2) { \
(dest).val = (src1).val - (src2).val; \
}
 
#define IS_AFTER(t1, t2) ((t2).val > (t1).val)
 
#define IS_AT_OR_AFTER(t1, t2) ((t2).val >= (t1).val)
 
#else
#if defined(SVR4) && !defined(sun) /* Sun claims SVR4, but
wants 2 args. */
#define GETTIMEOFDAY(_x) gettimeofday(_x)
#else
#define GETTIMEOFDAY(_x) gettimeofday(_x, NULL)
#endif
#define ADD_TIME(dest, src1, src2) { \
if(((dest).tv_usec = \
(src1).tv_usec + (src2).tv_usec) >= 1000000) { \
(dest).tv_usec -= 1000000; \
(dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1; \
} else { \
(dest).tv_sec = (src1).tv_sec + (src2).tv_sec; \
if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
(dest).tv_sec --;(dest).tv_usec += 1000000; \
} \
} \
}
#define TIMEDELTA(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) { \
(dest).tv_usec += 1000000; \
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1; \
} else { \
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec; \
} \
}
#define IS_AFTER(t1, t2) \
(((t2).tv_sec > (t1).tv_sec) || \
(((t2).tv_sec == (t1).tv_sec) && \
((t2).tv_usec > (t1).tv_usec)))
#define IS_AT_OR_AFTER(t1, t2) \
(((t2).tv_sec > (t1).tv_sec) || \
(((t2).tv_sec == (t1).tv_sec) && \
((t2).tv_usec >= (t1).tv_usec)))
#endif
 
#define IGNORE_IN_GAME_MODE() \
{ if (__glutGameModeWindow) return; }
 
#define GLUT_WIND_IS_RGB(x) (((x) & GLUT_INDEX) == 0)
#define GLUT_WIND_IS_INDEX(x) (((x) & GLUT_INDEX) != 0)
#define GLUT_WIND_IS_SINGLE(x) (((x) & GLUT_DOUBLE) == 0)
#define GLUT_WIND_IS_DOUBLE(x) (((x) & GLUT_DOUBLE) != 0)
#define GLUT_WIND_HAS_ACCUM(x) (((x) & GLUT_ACCUM) != 0)
#define GLUT_WIND_HAS_ALPHA(x) (((x) & GLUT_ALPHA) != 0)
#define GLUT_WIND_HAS_DEPTH(x) (((x) & GLUT_DEPTH) != 0)
#define GLUT_WIND_HAS_STENCIL(x) (((x) & GLUT_STENCIL) != 0)
#define GLUT_WIND_IS_MULTISAMPLE(x) (((x) & GLUT_MULTISAMPLE) != 0)
#define GLUT_WIND_IS_STEREO(x) (((x) & GLUT_STEREO) != 0)
#define GLUT_WIND_IS_LUMINANCE(x) (((x) & GLUT_LUMINANCE) != 0)
#define GLUT_MAP_WORK (1 << 0)
#define GLUT_EVENT_MASK_WORK (1 << 1)
#define GLUT_REDISPLAY_WORK (1 << 2)
#define GLUT_CONFIGURE_WORK (1 << 3)
#define GLUT_COLORMAP_WORK (1 << 4)
#define GLUT_DEVICE_MASK_WORK (1 << 5)
#define GLUT_FINISH_WORK (1 << 6)
#define GLUT_DEBUG_WORK (1 << 7)
#define GLUT_DUMMY_WORK (1 << 8)
#define GLUT_FULL_SCREEN_WORK (1 << 9)
#define GLUT_OVERLAY_REDISPLAY_WORK (1 << 10)
#define GLUT_REPAIR_WORK (1 << 11)
#define GLUT_OVERLAY_REPAIR_WORK (1 << 12)
 
/* Frame buffer capability macros and types. */
#define RGBA 0
#define BUFFER_SIZE 1
#define DOUBLEBUFFER 2
#define STEREO 3
#define AUX_BUFFERS 4
#define RED_SIZE 5 /* Used as mask bit for
"color selected". */
#define GREEN_SIZE 6
#define BLUE_SIZE 7
#define ALPHA_SIZE 8
#define DEPTH_SIZE 9
#define STENCIL_SIZE 10
#define ACCUM_RED_SIZE 11 /* Used as mask bit for
"acc selected". */
#define ACCUM_GREEN_SIZE 12
#define ACCUM_BLUE_SIZE 13
#define ACCUM_ALPHA_SIZE 14
#define LEVEL 15
 
#define NUM_GLXCAPS (LEVEL + 1)
 
#define XVISUAL (NUM_GLXCAPS + 0)
#define TRANSPARENT (NUM_GLXCAPS + 1)
#define SAMPLES (NUM_GLXCAPS + 2)
#define XSTATICGRAY (NUM_GLXCAPS + 3) /* Used as
mask bit
for "any
visual type
selected". */
#define XGRAYSCALE (NUM_GLXCAPS + 4)
#define XSTATICCOLOR (NUM_GLXCAPS + 5)
#define XPSEUDOCOLOR (NUM_GLXCAPS + 6)
#define XTRUECOLOR (NUM_GLXCAPS + 7)
#define XDIRECTCOLOR (NUM_GLXCAPS + 8)
#define SLOW (NUM_GLXCAPS + 9)
#define CONFORMANT (NUM_GLXCAPS + 10)
 
#define NUM_CAPS (NUM_GLXCAPS + 11)
 
/* Frame buffer capablities that don't have a corresponding
FrameBufferMode entry. These get used as mask bits. */
#define NUM (NUM_CAPS + 0)
#define RGBA_MODE (NUM_CAPS + 1)
#define CI_MODE (NUM_CAPS + 2)
#define LUMINANCE_MODE (NUM_CAPS + 3)
 
#define NONE 0
#define EQ 1
#define NEQ 2
#define LTE 3
#define GTE 4
#define GT 5
#define LT 6
#define MIN 7
 
typedef struct _Criterion {
int capability;
int comparison;
int value;
} Criterion;
 
typedef struct _FrameBufferMode {
XVisualInfo *vi;
#if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_fbconfig)
 
/* fbc is non-NULL when the XVisualInfo* is not OpenGL-capable
(ie, GLX_USE_GL is false), but the SGIX_fbconfig extension shows
the visual's fbconfig is OpenGL-capable. The reason for this is typically
an RGBA luminance fbconfig such as 16-bit StaticGray that could
not be advertised as a GLX visual since StaticGray visuals are
required (by the GLX specification) to be color index. The
SGIX_fbconfig allows StaticGray visuals to instead advertised as
fbconfigs that can provide RGBA luminance support. */
 
GLXFBConfigSGIX fbc;
#endif
int valid;
int cap[NUM_CAPS];
} FrameBufferMode;
 
/* DisplayMode capability macros for game mode. */
#define DM_WIDTH 0 /* "width" */
#define DM_HEIGHT 1 /* "height" */
#define DM_PIXEL_DEPTH 2 /* "bpp" (bits per pixel) */
#define DM_HERTZ 3 /* "hertz" */
#define DM_NUM 4 /* "num" */
 
#define NUM_DM_CAPS (DM_NUM+1)
 
typedef struct _DisplayMode {
#ifdef _WIN32
DEVMODE devmode;
#else
/* XXX The X Window System does not have a standard
mechanism for display setting changes. On SGI
systems, GLUT could use the XSGIvc (SGI X video
control extension). Perhaps this can be done in
a future release of GLUT. */
#endif
int valid;
int cap[NUM_DM_CAPS];
} DisplayMode;
 
/* GLUT function types */
typedef void (GLUTCALLBACK *GLUTdisplayCB) (void);
typedef void (GLUTCALLBACK *GLUTreshapeCB) (int, int);
typedef void (GLUTCALLBACK *GLUTkeyboardCB) (unsigned char, int, int);
typedef void (GLUTCALLBACK *GLUTmouseCB) (int, int, int, int);
typedef void (GLUTCALLBACK *GLUTmotionCB) (int, int);
typedef void (GLUTCALLBACK *GLUTpassiveCB) (int, int);
typedef void (GLUTCALLBACK *GLUTentryCB) (int);
typedef void (GLUTCALLBACK *GLUTvisibilityCB) (int);
typedef void (GLUTCALLBACK *GLUTwindowStatusCB) (int);
typedef void (GLUTCALLBACK *GLUTidleCB) (void);
typedef void (GLUTCALLBACK *GLUTtimerCB) (int);
typedef void (GLUTCALLBACK *GLUTmenuStateCB) (int); /* DEPRICATED. */
typedef void (GLUTCALLBACK *GLUTmenuStatusCB) (int, int, int);
typedef void (GLUTCALLBACK *GLUTselectCB) (int);
typedef void (GLUTCALLBACK *GLUTspecialCB) (int, int, int);
typedef void (GLUTCALLBACK *GLUTspaceMotionCB) (int, int, int);
typedef void (GLUTCALLBACK *GLUTspaceRotateCB) (int, int, int);
typedef void (GLUTCALLBACK *GLUTspaceButtonCB) (int, int);
typedef void (GLUTCALLBACK *GLUTdialsCB) (int, int);
typedef void (GLUTCALLBACK *GLUTbuttonBoxCB) (int, int);
typedef void (GLUTCALLBACK *GLUTtabletMotionCB) (int, int);
typedef void (GLUTCALLBACK *GLUTtabletButtonCB) (int, int, int, int);
typedef void (GLUTCALLBACK *GLUTjoystickCB) (unsigned int buttonMask, int x, int y, int z);
 
typedef struct _GLUTcolorcell GLUTcolorcell;
struct _GLUTcolorcell {
/* GLUT_RED, GLUT_GREEN, GLUT_BLUE */
GLfloat component[3];
};
 
typedef struct _GLUTcolormap GLUTcolormap;
struct _GLUTcolormap {
Visual *visual; /* visual of the colormap */
Colormap cmap; /* X colormap ID */
int refcnt; /* number of windows using colormap */
int size; /* number of cells in colormap */
int transparent; /* transparent pixel, or -1 if opaque */
GLUTcolorcell *cells; /* array of cells */
GLUTcolormap *next; /* next colormap in list */
};
 
typedef struct _GLUTwindow GLUTwindow;
typedef struct _GLUToverlay GLUToverlay;
struct _GLUTwindow {
int num; /* Small integer window id (0-based). */
 
/* Window system related state. */
#if defined(_WIN32)
int pf; /* Pixel format. */
HDC hdc; /* Window's Win32 device context. */
#endif
Window win; /* X window for GLUT window */
GLXContext ctx; /* OpenGL context GLUT glut window */
XVisualInfo *vis; /* visual for window */
Bool visAlloced; /* if vis needs deallocate on destroy */
Colormap cmap; /* RGB colormap for window; None if CI */
GLUTcolormap *colormap; /* colormap; NULL if RGBA */
GLUToverlay *overlay; /* overlay; NULL if no overlay */
#if defined(_WIN32)
HDC renderDc; /* Win32's device context for rendering. */
#endif
Window renderWin; /* X window for rendering (might be
overlay) */
GLXContext renderCtx; /* OpenGL context for rendering (might
be overlay) */
/* GLUT settable or visible window state. */
int width; /* window width in pixels */
int height; /* window height in pixels */
int cursor; /* cursor name */
int visState; /* visibility state (-1 is unknown) */
int shownState; /* if window mapped */
int entryState; /* entry state (-1 is unknown) */
#define GLUT_MAX_MENUS 3
 
int menu[GLUT_MAX_MENUS]; /* attatched menu nums */
/* Window relationship state. */
GLUTwindow *parent; /* parent window */
GLUTwindow *children; /* list of children */
GLUTwindow *siblings; /* list of siblings */
/* Misc. non-API visible (hidden) state. */
Bool treatAsSingle; /* treat this window as single-buffered
(it might be "fake" though) */
Bool forceReshape; /* force reshape before display */
#if !defined(_WIN32)
Bool isDirect; /* if direct context (X11 only) */
#endif
Bool usedSwapBuffers; /* if swap buffers used last display */
long eventMask; /* mask of X events selected for */
int buttonUses; /* number of button uses, ref cnt */
int tabletPos[2]; /* tablet position (-1 is invalid) */
/* Work list related state. */
unsigned int workMask; /* mask of window work to be done */
GLUTwindow *prevWorkWin; /* link list of windows to work on */
Bool desiredMapState; /* how to mapped window if on map work
list */
Bool ignoreKeyRepeat; /* if window ignores autorepeat */
int desiredConfMask; /* mask of desired window configuration
*/
int desiredX; /* desired X location */
int desiredY; /* desired Y location */
int desiredWidth; /* desired window width */
int desiredHeight; /* desired window height */
int desiredStack; /* desired window stack */
/* Per-window callbacks. */
GLUTdisplayCB display; /* redraw */
GLUTreshapeCB reshape; /* resize (width,height) */
GLUTmouseCB mouse; /* mouse (button,state,x,y) */
GLUTmotionCB motion; /* motion (x,y) */
GLUTpassiveCB passive; /* passive motion (x,y) */
GLUTentryCB entry; /* window entry/exit (state) */
GLUTkeyboardCB keyboard; /* keyboard (ASCII,x,y) */
GLUTkeyboardCB keyboardUp; /* keyboard up (ASCII,x,y) */
GLUTwindowStatusCB windowStatus; /* window status */
GLUTvisibilityCB visibility; /* visibility */
GLUTspecialCB special; /* special key */
GLUTspecialCB specialUp; /* special up key */
GLUTbuttonBoxCB buttonBox; /* button box */
GLUTdialsCB dials; /* dials */
GLUTspaceMotionCB spaceMotion; /* Spaceball motion */
GLUTspaceRotateCB spaceRotate; /* Spaceball rotate */
GLUTspaceButtonCB spaceButton; /* Spaceball button */
GLUTtabletMotionCB tabletMotion; /* tablet motion */
GLUTtabletButtonCB tabletButton; /* tablet button */
#ifdef _WIN32
GLUTjoystickCB joystick; /* joystick */
int joyPollInterval; /* joystick polling interval */
#endif
#ifdef SUPPORT_FORTRAN
GLUTdisplayFCB fdisplay; /* Fortran display */
GLUTreshapeFCB freshape; /* Fortran reshape */
GLUTmouseFCB fmouse; /* Fortran mouse */
GLUTmotionFCB fmotion; /* Fortran motion */
GLUTpassiveFCB fpassive; /* Fortran passive */
GLUTentryFCB fentry; /* Fortran entry */
GLUTkeyboardFCB fkeyboard; /* Fortran keyboard */
GLUTkeyboardFCB fkeyboardUp; /* Fortran keyboard up */
GLUTwindowStatusFCB fwindowStatus; /* Fortran window status */
GLUTvisibilityFCB fvisibility; /* Fortran visibility */
GLUTspecialFCB fspecial; /* special key */
GLUTspecialFCB fspecialUp; /* special key up */
GLUTbuttonBoxFCB fbuttonBox; /* button box */
GLUTdialsFCB fdials; /* dials */
GLUTspaceMotionFCB fspaceMotion; /* Spaceball motion */
GLUTspaceRotateFCB fspaceRotate; /* Spaceball rotate */
GLUTspaceButtonFCB fspaceButton; /* Spaceball button */
GLUTtabletMotionFCB ftabletMotion; /* tablet motion */
GLUTtabletButtonFCB ftabletButton; /* tablet button */
#ifdef _WIN32
GLUTjoystickFCB fjoystick; /* joystick */
#endif
#endif
};
 
struct _GLUToverlay {
#if defined(_WIN32)
int pf;
HDC hdc;
#endif
Window win;
GLXContext ctx;
XVisualInfo *vis; /* visual for window */
Bool visAlloced; /* if vis needs deallocate on destroy */
Colormap cmap; /* RGB colormap for window; None if CI */
GLUTcolormap *colormap; /* colormap; NULL if RGBA */
int shownState; /* if overlay window mapped */
Bool treatAsSingle; /* treat as single-buffered */
#if !defined(_WIN32)
Bool isDirect; /* if direct context */
#endif
int transparentPixel; /* transparent pixel value */
GLUTdisplayCB display; /* redraw */
#ifdef SUPPORT_FORTRAN
GLUTdisplayFCB fdisplay; /* redraw */
#endif
};
 
typedef struct _GLUTstale GLUTstale;
struct _GLUTstale {
GLUTwindow *window;
Window win;
GLUTstale *next;
};
 
extern GLUTstale *__glutStaleWindowList;
 
#define GLUT_OVERLAY_EVENT_FILTER_MASK \
(ExposureMask | \
StructureNotifyMask | \
EnterWindowMask | \
LeaveWindowMask)
#define GLUT_DONT_PROPAGATE_FILTER_MASK \
(ButtonReleaseMask | \
ButtonPressMask | \
KeyPressMask | \
KeyReleaseMask | \
PointerMotionMask | \
Button1MotionMask | \
Button2MotionMask | \
Button3MotionMask)
#define GLUT_HACK_STOP_PROPAGATE_MASK \
(KeyPressMask | \
KeyReleaseMask)
 
typedef struct _GLUTmenu GLUTmenu;
typedef struct _GLUTmenuItem GLUTmenuItem;
struct _GLUTmenu {
int id; /* small integer menu id (0-based) */
Window win; /* X window for the menu */
GLUTselectCB select; /* function of menu */
GLUTmenuItem *list; /* list of menu entries */
int num; /* number of entries */
#if !defined(_WIN32)
Bool managed; /* are the InputOnly windows size
validated? */
Bool searched; /* help detect menu loops */
int pixheight; /* height of menu in pixels */
int pixwidth; /* width of menu in pixels */
#endif
int submenus; /* number of submenu entries */
GLUTmenuItem *highlighted; /* pointer to highlighted menu
entry, NULL not highlighted */
GLUTmenu *cascade; /* currently cascading this menu */
GLUTmenuItem *anchor; /* currently anchored to this entry */
int x; /* current x origin relative to the
root window */
int y; /* current y origin relative to the
root window */
#ifdef SUPPORT_FORTRAN
GLUTselectFCB fselect; /* function of menu */
#endif
};
 
struct _GLUTmenuItem {
Window win; /* InputOnly X window for entry */
GLUTmenu *menu; /* menu entry belongs to */
Bool isTrigger; /* is a submenu trigger? */
int value; /* value to return for selecting this
entry; doubles as submenu id
(0-base) if submenu trigger */
#if defined(_WIN32)
UINT unique; /* unique menu item id (Win32 only) */
#endif
char *label; /* __glutStrdup'ed label string */
int len; /* length of label string */
int pixwidth; /* width of X window in pixels */
GLUTmenuItem *next; /* next menu entry on list for menu */
};
 
typedef struct _GLUTtimer GLUTtimer;
struct _GLUTtimer {
GLUTtimer *next; /* list of timers */
#ifdef OLD_VMS
struct timeval6 timeout; /* time to be called */
#else
struct timeval timeout; /* time to be called */
#endif
GLUTtimerCB func; /* timer (value) */
int value; /* return value */
#ifdef SUPPORT_FORTRAN
GLUTtimerFCB ffunc; /* Fortran timer */
#endif
};
 
typedef struct _GLUTeventParser GLUTeventParser;
struct _GLUTeventParser {
int (*func) (XEvent *);
GLUTeventParser *next;
};
 
/* Declarations to implement glutFullScreen support with
mwm/4Dwm. */
 
/* The following X property format is defined in Motif 1.1's
Xm/MwmUtils.h, but GLUT should not depend on that header
file. Note: Motif 1.2 expanded this structure with
uninteresting fields (to GLUT) so just stick with the
smaller Motif 1.1 structure. */
typedef struct {
#define MWM_HINTS_DECORATIONS 2
long flags;
long functions;
long decorations;
long input_mode;
} MotifWmHints;
 
/* Make current and buffer swap macros. */
#ifdef _WIN32
#define MAKE_CURRENT_LAYER(window) \
{ \
HGLRC currentContext = wglGetCurrentContext(); \
HDC currentDc = wglGetCurrentDC(); \
\
if (currentContext != window->renderCtx \
|| currentDc != window->renderDc) { \
wglMakeCurrent(window->renderDc, window->renderCtx); \
} \
}
#define MAKE_CURRENT_WINDOW(window) \
{ \
HGLRC currentContext = wglGetCurrentContext(); \
HDC currentDc = wglGetCurrentDC(); \
\
if (currentContext != window->ctx || currentDc != window->hdc) { \
wglMakeCurrent(window->hdc, window->ctx); \
} \
}
#define MAKE_CURRENT_OVERLAY(overlay) \
wglMakeCurrent(overlay->hdc, overlay->ctx)
#define UNMAKE_CURRENT() \
wglMakeCurrent(NULL, NULL)
#define SWAP_BUFFERS_WINDOW(window) \
SwapBuffers(window->hdc)
#define SWAP_BUFFERS_LAYER(window) \
SwapBuffers(window->renderDc)
#else
#define MAKE_CURRENT_LAYER(window) \
glXMakeCurrent(__glutDisplay, window->renderWin, window->renderCtx)
#define MAKE_CURRENT_WINDOW(window) \
glXMakeCurrent(__glutDisplay, window->win, window->ctx)
#define MAKE_CURRENT_OVERLAY(overlay) \
glXMakeCurrent(__glutDisplay, overlay->win, overlay->ctx)
#define UNMAKE_CURRENT() \
glXMakeCurrent(__glutDisplay, None, NULL)
#define SWAP_BUFFERS_WINDOW(window) \
glXSwapBuffers(__glutDisplay, window->win)
#define SWAP_BUFFERS_LAYER(window) \
glXSwapBuffers(__glutDisplay, window->renderWin)
#endif
 
/* private variables from glut_event.c */
extern GLUTwindow *__glutWindowWorkList;
extern int __glutWindowDamaged;
#ifdef SUPPORT_FORTRAN
extern GLUTtimer *__glutTimerList;
extern GLUTtimer *__glutNewTimer;
#endif
extern GLUTmenu *__glutMappedMenu;
 
extern void (*__glutUpdateInputDeviceMaskFunc) (GLUTwindow *);
#if !defined(_WIN32)
extern void (*__glutMenuItemEnterOrLeave)(GLUTmenuItem * item,
int num, int type);
extern void (*__glutFinishMenu)(Window win, int x, int y);
extern void (*__glutPaintMenu)(GLUTmenu * menu);
extern void (*__glutStartMenu)(GLUTmenu * menu,
GLUTwindow * window, int x, int y, int x_win, int y_win);
extern GLUTmenu * (*__glutGetMenuByNum)(int menunum);
extern GLUTmenuItem * (*__glutGetMenuItem)(GLUTmenu * menu,
Window win, int *which);
extern GLUTmenu * (*__glutGetMenu)(Window win);
#endif
 
/* private variables from glut_init.c */
extern Atom __glutWMDeleteWindow;
extern Display *__glutDisplay;
extern unsigned int __glutDisplayMode;
extern char *__glutDisplayString;
extern XVisualInfo *(*__glutDetermineVisualFromString) (char *string, Bool * treatAsSingle,
Criterion * requiredCriteria, int nRequired, int requiredMask, void **fbc);
extern GLboolean __glutDebug;
extern GLboolean __glutForceDirect;
extern GLboolean __glutIconic;
extern GLboolean __glutTryDirect;
extern Window __glutRoot;
extern XSizeHints __glutSizeHints;
extern char **__glutArgv;
extern char *__glutProgramName;
extern int __glutArgc;
extern int __glutConnectionFD;
extern int __glutInitHeight;
extern int __glutInitWidth;
extern int __glutInitX;
extern int __glutInitY;
extern int __glutScreen;
extern int __glutScreenHeight;
extern int __glutScreenWidth;
extern Atom __glutMotifHints;
extern unsigned int __glutModifierMask;
#ifdef _WIN32
extern void (__cdecl *__glutExitFunc)(int retval);
#endif
extern char *__glutPPMFile;
 
/* private variables from glut_menu.c */
extern GLUTmenuItem *__glutItemSelected;
extern GLUTmenu **__glutMenuList;
extern void (GLUTCALLBACK *__glutMenuStatusFunc) (int, int, int);
extern void __glutMenuModificationError(void);
extern void __glutSetMenuItem(GLUTmenuItem * item,
const char *label, int value, Bool isTrigger);
 
/* private variables from glut_win.c */
extern GLUTwindow **__glutWindowList;
extern GLUTwindow *__glutCurrentWindow;
extern GLUTwindow *__glutMenuWindow;
extern GLUTmenu *__glutCurrentMenu;
extern int __glutWindowListSize;
extern void (*__glutFreeOverlayFunc) (GLUToverlay *);
extern void __glutFreeOverlay(GLUToverlay * overlay);
extern XVisualInfo *__glutDetermineWindowVisual(Bool * treatAsSingle,
Bool * visAlloced, void **fbc);
 
/* private variables from glut_ppm.c */
extern void __glutWritePPMFile(void);
 
/* private variables from glut_mesa.c */
extern int __glutMesaSwapHackSupport;
 
/* private variables from glut_gamemode.c */
extern GLUTwindow *__glutGameModeWindow;
 
/* private routines from glut_cindex.c */
extern GLUTcolormap * __glutAssociateNewColormap(XVisualInfo * vis);
extern void __glutFreeColormap(GLUTcolormap *);
 
/* private routines from glut_cmap.c */
extern void __glutSetupColormap(
XVisualInfo * vi,
GLUTcolormap ** colormap,
Colormap * cmap);
#if !defined(_WIN32)
extern void __glutEstablishColormapsProperty(
GLUTwindow * window);
extern GLUTwindow *__glutToplevelOf(GLUTwindow * window);
#endif
 
/* private routines from glut_cursor.c */
extern void __glutSetCursor(GLUTwindow *window);
 
/* private routines from glut_event.c */
extern void __glutPutOnWorkList(GLUTwindow * window,
int work_mask);
extern void __glutRegisterEventParser(GLUTeventParser * parser);
extern void __glutPostRedisplay(GLUTwindow * window, int layerMask);
extern void handleTimeouts(void);
 
/* private routines from glut_init.c */
#if !defined(_WIN32)
extern void __glutOpenXConnection(char *display);
#else
extern void __glutOpenWin32Connection(char *display);
#endif
#ifdef OLD_VMS
extern void __glutInitTime(struct timeval6 *beginning);
#else
extern void __glutInitTime(struct timeval *beginning);
#endif
 
/* private routines for glut_menu.c (or win32_menu.c) */
#if defined(_WIN32)
extern GLUTmenu *__glutGetMenu(Window win);
extern GLUTmenu *__glutGetMenuByNum(int menunum);
extern GLUTmenuItem *__glutGetMenuItem(GLUTmenu * menu,
Window win, int *which);
extern void __glutStartMenu(GLUTmenu * menu,
GLUTwindow * window, int x, int y, int x_win, int y_win);
extern void __glutFinishMenu(Window win, int x, int y);
#endif
extern void __glutSetMenu(GLUTmenu * menu);
 
/* private routines from glut_util.c */
extern char * __glutStrdup(const char *string);
extern void __glutWarning(char *format,...);
extern void __glutFatalError(char *format,...);
extern void __glutFatalUsage(char *format,...);
 
/* private routines from glut_win.c */
extern GLUTwindow *__glutGetWindow(Window win);
extern void __glutChangeWindowEventMask(long mask, Bool add);
extern XVisualInfo *__glutDetermineVisual(
unsigned int mode,
Bool * fakeSingle,
XVisualInfo * (getVisualInfo) (unsigned int));
extern XVisualInfo *__glutGetVisualInfo(unsigned int mode);
extern void __glutSetWindow(GLUTwindow * window);
extern void __glutReshapeFunc(GLUTreshapeCB reshapeFunc,
int callingConvention);
extern void GLUTCALLBACK __glutDefaultReshape(int, int);
extern GLUTwindow *__glutCreateWindow(
GLUTwindow * parent,
int x, int y, int width, int height, int gamemode);
extern void __glutDestroyWindow(
GLUTwindow * window,
GLUTwindow * initialWindow);
 
#if !defined(_WIN32)
/* private routines from glut_glxext.c */
extern int __glutIsSupportedByGLX(char *);
extern int __glut_glXBindChannelToWindowSGIX(Display *dpy, int screen,
int channel, Window window);
extern int __glut_glXChannelRectSGIX(Display *dpy, int screen, int channel,
int x, int y, int w, int h);
extern int __glut_glXQueryChannelRectSGIX(Display *dpy, int screen,
int channel, int *x, int *y,
int *w, int *h);
extern int __glut_glXQueryChannelDeltasSGIX(Display *dpy, int screen,
int channel, int *dx, int *dy,
int *dw, int *dh);
extern int __glut_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel,
GLenum synctype);
extern GLXContext __glut_glXCreateContextWithConfigSGIX(Display *dpy,
GLXFBConfigSGIX config,
int render_type,
GLXContext share_list,
Bool direct);
extern int __glut_glXGetFBConfigAttribSGIX(Display *dpy,
GLXFBConfigSGIX config,
int attribute,
int *value);
extern GLXFBConfigSGIX __glut_glXGetFBConfigFromVisualSGIX(Display *dpy,
XVisualInfo *vis);
#endif
 
/* private routines from glut_input.c */
extern void __glutUpdateInputDeviceMask(GLUTwindow * window);
 
/* private routines from glut_mesa.c */
extern void __glutDetermineMesaSwapHackSupport(void);
 
/* private routines from glut_gameglut.c */
extern void __glutCloseDownGameMode(void);
 
/* private variables from glut_swap.c (BrianP) */
extern GLint __glutFPS;
extern GLint __glutSwapCount;
extern GLint __glutSwapTime;
 
#if defined(_WIN32)
/* private routines from win32_*.c */
extern LONG WINAPI __glutWindowProc(HWND win, UINT msg, WPARAM w, LPARAM l);
extern HDC XHDC;
#endif
 
 
#endif /* __glutint_h__ */
/contrib/sdk/samples/Mesa/mipmap.c
0,0 → 1,8940
/*
* 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.
*/
 
#include "gluos.h"
#include <assert.h>
#include <GL/glu.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* UINT_MAX */
#include <math.h>
 
typedef union {
unsigned char ub[4];
unsigned short us[2];
unsigned int ui;
char b[4];
short s[2];
int i;
float f;
} Type_Widget;
 
/* Pixel storage modes */
typedef struct {
GLint pack_alignment;
GLint pack_row_length;
GLint pack_skip_rows;
GLint pack_skip_pixels;
GLint pack_lsb_first;
GLint pack_swap_bytes;
GLint pack_skip_images;
GLint pack_image_height;
 
GLint unpack_alignment;
GLint unpack_row_length;
GLint unpack_skip_rows;
GLint unpack_skip_pixels;
GLint unpack_lsb_first;
GLint unpack_swap_bytes;
GLint unpack_skip_images;
GLint unpack_image_height;
} PixelStorageModes;
 
static int gluBuild1DMipmapLevelsCore(GLenum, GLint,
GLsizei,
GLsizei,
GLenum, GLenum, GLint, GLint, GLint,
const void *);
static int gluBuild2DMipmapLevelsCore(GLenum, GLint,
GLsizei, GLsizei,
GLsizei, GLsizei,
GLenum, GLenum, GLint, GLint, GLint,
const void *);
static int gluBuild3DMipmapLevelsCore(GLenum, GLint,
GLsizei, GLsizei, GLsizei,
GLsizei, GLsizei, GLsizei,
GLenum, GLenum, GLint, GLint, GLint,
const void *);
 
/*
* internal function declarations
*/
static GLfloat bytes_per_element(GLenum type);
static GLint elements_per_group(GLenum format, GLenum type);
static GLint is_index(GLenum format);
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type);
static void fill_image(const PixelStorageModes *,
GLint width, GLint height, GLenum format,
GLenum type, GLboolean index_format,
const void *userdata, GLushort *newimage);
static void empty_image(const PixelStorageModes *,
GLint width, GLint height, GLenum format,
GLenum type, GLboolean index_format,
const GLushort *oldimage, void *userdata);
static void scale_internal(GLint components, GLint widthin, GLint heightin,
const GLushort *datain,
GLint widthout, GLint heightout,
GLushort *dataout);
 
static void scale_internal_ubyte(GLint components, GLint widthin,
GLint heightin, const GLubyte *datain,
GLint widthout, GLint heightout,
GLubyte *dataout, GLint element_size,
GLint ysize, GLint group_size);
static void scale_internal_byte(GLint components, GLint widthin,
GLint heightin, const GLbyte *datain,
GLint widthout, GLint heightout,
GLbyte *dataout, GLint element_size,
GLint ysize, GLint group_size);
static void scale_internal_ushort(GLint components, GLint widthin,
GLint heightin, const GLushort *datain,
GLint widthout, GLint heightout,
GLushort *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes);
static void scale_internal_short(GLint components, GLint widthin,
GLint heightin, const GLshort *datain,
GLint widthout, GLint heightout,
GLshort *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes);
static void scale_internal_uint(GLint components, GLint widthin,
GLint heightin, const GLuint *datain,
GLint widthout, GLint heightout,
GLuint *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes);
static void scale_internal_int(GLint components, GLint widthin,
GLint heightin, const GLint *datain,
GLint widthout, GLint heightout,
GLint *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes);
static void scale_internal_float(GLint components, GLint widthin,
GLint heightin, const GLfloat *datain,
GLint widthout, GLint heightout,
GLfloat *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes);
 
static int checkMipmapArgs(GLenum, GLenum, GLenum);
static GLboolean legalFormat(GLenum);
static GLboolean legalType(GLenum);
static GLboolean isTypePackedPixel(GLenum);
static GLboolean isLegalFormatForPackedPixelType(GLenum, GLenum);
static GLboolean isLegalLevels(GLint, GLint, GLint, GLint);
static void closestFit(GLenum, GLint, GLint, GLint, GLenum, GLenum,
GLint *, GLint *);
 
/* all extract/shove routines must return double to handle unsigned ints */
static GLdouble extractUbyte(int, const void *);
static void shoveUbyte(GLdouble, int, void *);
static GLdouble extractSbyte(int, const void *);
static void shoveSbyte(GLdouble, int, void *);
static GLdouble extractUshort(int, const void *);
static void shoveUshort(GLdouble, int, void *);
static GLdouble extractSshort(int, const void *);
static void shoveSshort(GLdouble, int, void *);
static GLdouble extractUint(int, const void *);
static void shoveUint(GLdouble, int, void *);
static GLdouble extractSint(int, const void *);
static void shoveSint(GLdouble, int, void *);
static GLdouble extractFloat(int, const void *);
static void shoveFloat(GLdouble, int, void *);
static void halveImageSlice(int, GLdouble (*)(int, const void *),
void (*)(GLdouble, int, void *),
GLint, GLint, GLint,
const void *, void *,
GLint, GLint, GLint, GLint, GLint);
static void halveImage3D(int, GLdouble (*)(int, const void *),
void (*)(GLdouble, int, void *),
GLint, GLint, GLint,
const void *, void *,
GLint, GLint, GLint, GLint, GLint);
 
/* packedpixel type scale routines */
static void extract332(int,const void *, GLfloat []);
static void shove332(const GLfloat [],int ,void *);
static void extract233rev(int,const void *, GLfloat []);
static void shove233rev(const GLfloat [],int ,void *);
static void extract565(int,const void *, GLfloat []);
static void shove565(const GLfloat [],int ,void *);
static void extract565rev(int,const void *, GLfloat []);
static void shove565rev(const GLfloat [],int ,void *);
static void extract4444(int,const void *, GLfloat []);
static void shove4444(const GLfloat [],int ,void *);
static void extract4444rev(int,const void *, GLfloat []);
static void shove4444rev(const GLfloat [],int ,void *);
static void extract5551(int,const void *, GLfloat []);
static void shove5551(const GLfloat [],int ,void *);
static void extract1555rev(int,const void *, GLfloat []);
static void shove1555rev(const GLfloat [],int ,void *);
static void extract8888(int,const void *, GLfloat []);
static void shove8888(const GLfloat [],int ,void *);
static void extract8888rev(int,const void *, GLfloat []);
static void shove8888rev(const GLfloat [],int ,void *);
static void extract1010102(int,const void *, GLfloat []);
static void shove1010102(const GLfloat [],int ,void *);
static void extract2101010rev(int,const void *, GLfloat []);
static void shove2101010rev(const GLfloat [],int ,void *);
static void scaleInternalPackedPixel(int,
void (*)(int, const void *,GLfloat []),
void (*)(const GLfloat [],int, void *),
GLint,GLint, const void *,
GLint,GLint,void *,GLint,GLint,GLint);
static void halveImagePackedPixel(int,
void (*)(int, const void *,GLfloat []),
void (*)(const GLfloat [],int, void *),
GLint, GLint, const void *,
void *, GLint, GLint, GLint);
static void halve1DimagePackedPixel(int,
void (*)(int, const void *,GLfloat []),
void (*)(const GLfloat [],int, void *),
GLint, GLint, const void *,
void *, GLint, GLint, GLint);
 
static void halve1Dimage_ubyte(GLint, GLuint, GLuint,const GLubyte *,
GLubyte *, GLint, GLint, GLint);
static void halve1Dimage_byte(GLint, GLuint, GLuint,const GLbyte *, GLbyte *,
GLint, GLint, GLint);
static void halve1Dimage_ushort(GLint, GLuint, GLuint, const GLushort *,
GLushort *, GLint, GLint, GLint, GLint);
static void halve1Dimage_short(GLint, GLuint, GLuint,const GLshort *, GLshort *,
GLint, GLint, GLint, GLint);
static void halve1Dimage_uint(GLint, GLuint, GLuint, const GLuint *, GLuint *,
GLint, GLint, GLint, GLint);
static void halve1Dimage_int(GLint, GLuint, GLuint, const GLint *, GLint *,
GLint, GLint, GLint, GLint);
static void halve1Dimage_float(GLint, GLuint, GLuint, const GLfloat *, GLfloat *,
GLint, GLint, GLint, GLint);
 
static GLint imageSize3D(GLint, GLint, GLint, GLenum,GLenum);
static void fillImage3D(const PixelStorageModes *, GLint, GLint, GLint,GLenum,
GLenum, GLboolean, const void *, GLushort *);
static void emptyImage3D(const PixelStorageModes *,
GLint, GLint, GLint, GLenum,
GLenum, GLboolean,
const GLushort *, void *);
static void scaleInternal3D(GLint, GLint, GLint, GLint, const GLushort *,
GLint, GLint, GLint, GLushort *);
 
static void retrieveStoreModes(PixelStorageModes *psm)
{
glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
 
glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
}
 
static void retrieveStoreModes3D(PixelStorageModes *psm)
{
glGetIntegerv(GL_UNPACK_ALIGNMENT, &psm->unpack_alignment);
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &psm->unpack_row_length);
glGetIntegerv(GL_UNPACK_SKIP_ROWS, &psm->unpack_skip_rows);
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &psm->unpack_skip_pixels);
glGetIntegerv(GL_UNPACK_LSB_FIRST, &psm->unpack_lsb_first);
glGetIntegerv(GL_UNPACK_SWAP_BYTES, &psm->unpack_swap_bytes);
glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &psm->unpack_skip_images);
glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &psm->unpack_image_height);
 
glGetIntegerv(GL_PACK_ALIGNMENT, &psm->pack_alignment);
glGetIntegerv(GL_PACK_ROW_LENGTH, &psm->pack_row_length);
glGetIntegerv(GL_PACK_SKIP_ROWS, &psm->pack_skip_rows);
glGetIntegerv(GL_PACK_SKIP_PIXELS, &psm->pack_skip_pixels);
glGetIntegerv(GL_PACK_LSB_FIRST, &psm->pack_lsb_first);
glGetIntegerv(GL_PACK_SWAP_BYTES, &psm->pack_swap_bytes);
glGetIntegerv(GL_PACK_SKIP_IMAGES, &psm->pack_skip_images);
glGetIntegerv(GL_PACK_IMAGE_HEIGHT, &psm->pack_image_height);
}
 
static int computeLog(GLuint value)
{
int i;
 
i = 0;
 
/* Error! */
if (value == 0) return -1;
 
for (;;) {
if (value & 1) {
/* Error ! */
if (value != 1) return -1;
return i;
}
value = value >> 1;
i++;
}
}
 
/*
** Compute the nearest power of 2 number. This algorithm is a little
** strange, but it works quite well.
*/
static int nearestPower(GLuint value)
{
int i;
 
i = 1;
 
/* Error! */
if (value == 0) return -1;
 
for (;;) {
if (value == 1) {
return i;
} else if (value == 3) {
return i*4;
}
value = value >> 1;
i *= 2;
}
}
 
#define __GLU_SWAP_2_BYTES(s)\
(GLushort)(((GLushort)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
 
#define __GLU_SWAP_4_BYTES(s)\
(GLuint)(((GLuint)((const GLubyte*)(s))[3])<<24 | \
((GLuint)((const GLubyte*)(s))[2])<<16 | \
((GLuint)((const GLubyte*)(s))[1])<<8 | ((const GLubyte*)(s))[0])
 
static void halveImage(GLint components, GLuint width, GLuint height,
const GLushort *datain, GLushort *dataout)
{
int i, j, k;
int newwidth, newheight;
int delta;
GLushort *s;
const GLushort *t;
 
newwidth = width / 2;
newheight = height / 2;
delta = width * components;
s = dataout;
t = datain;
 
/* Piece o' cake! */
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (t[0] + t[components] + t[delta] +
t[delta+components] + 2) / 4;
s++; t++;
}
t += components;
}
t += delta;
}
}
 
static void halveImage_ubyte(GLint components, GLuint width, GLuint height,
const GLubyte *datain, GLubyte *dataout,
GLint element_size, GLint ysize, GLint group_size)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLubyte *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_ubyte(components,width,height,datain,dataout,
element_size,ysize,group_size);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (*(const GLubyte*)t +
*(const GLubyte*)(t+group_size) +
*(const GLubyte*)(t+ysize) +
*(const GLubyte*)(t+ysize+group_size) + 2) / 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
/* */
static void halve1Dimage_ubyte(GLint components, GLuint width, GLuint height,
const GLubyte *dataIn, GLubyte *dataOut,
GLint element_size, GLint ysize,
GLint group_size)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLubyte *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
*dest= (*(const GLubyte*)src +
*(const GLubyte*)(src+group_size)) / 2;
 
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
*dest= (*(const GLubyte*)src + *(const GLubyte*)(src+ysize)) / 2;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
} /* halve1Dimage_ubyte() */
 
static void halveImage_byte(GLint components, GLuint width, GLuint height,
const GLbyte *datain, GLbyte *dataout,
GLint element_size,
GLint ysize, GLint group_size)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLbyte *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_byte(components,width,height,datain,dataout,
element_size,ysize,group_size);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (*(const GLbyte*)t +
*(const GLbyte*)(t+group_size) +
*(const GLbyte*)(t+ysize) +
*(const GLbyte*)(t+ysize+group_size) + 2) / 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
static void halve1Dimage_byte(GLint components, GLuint width, GLuint height,
const GLbyte *dataIn, GLbyte *dataOut,
GLint element_size,GLint ysize, GLint group_size)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLbyte *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
*dest= (*(const GLbyte*)src + *(const GLbyte*)(src+group_size)) / 2;
 
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
*dest= (*(const GLbyte*)src + *(const GLbyte*)(src+ysize)) / 2;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
}
 
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
} /* halve1Dimage_byte() */
 
static void halveImage_ushort(GLint components, GLuint width, GLuint height,
const GLushort *datain, GLushort *dataout,
GLint element_size, GLint ysize, GLint group_size,
GLint myswap_bytes)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLushort *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_ushort(components,width,height,datain,dataout,
element_size,ysize,group_size, myswap_bytes);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
if (!myswap_bytes)
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (*(const GLushort*)t +
*(const GLushort*)(t+group_size) +
*(const GLushort*)(t+ysize) +
*(const GLushort*)(t+ysize+group_size) + 2) / 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
else
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (__GLU_SWAP_2_BYTES(t) +
__GLU_SWAP_2_BYTES(t+group_size) +
__GLU_SWAP_2_BYTES(t+ysize) +
__GLU_SWAP_2_BYTES(t+ysize+group_size)+ 2)/4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
static void halve1Dimage_ushort(GLint components, GLuint width, GLuint height,
const GLushort *dataIn, GLushort *dataOut,
GLint element_size, GLint ysize,
GLint group_size, GLint myswap_bytes)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLushort *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLushort ushort[BOX2];
if (myswap_bytes) {
ushort[0]= __GLU_SWAP_2_BYTES(src);
ushort[1]= __GLU_SWAP_2_BYTES(src+group_size);
}
else {
ushort[0]= *(const GLushort*)src;
ushort[1]= *(const GLushort*)(src+group_size);
}
 
*dest= (ushort[0] + ushort[1]) / 2;
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLushort ushort[BOX2];
if (myswap_bytes) {
ushort[0]= __GLU_SWAP_2_BYTES(src);
ushort[1]= __GLU_SWAP_2_BYTES(src+ysize);
}
else {
ushort[0]= *(const GLushort*)src;
ushort[1]= *(const GLushort*)(src+ysize);
}
*dest= (ushort[0] + ushort[1]) / 2;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
}
 
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
 
} /* halve1Dimage_ushort() */
 
 
static void halveImage_short(GLint components, GLuint width, GLuint height,
const GLshort *datain, GLshort *dataout,
GLint element_size, GLint ysize, GLint group_size,
GLint myswap_bytes)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLshort *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_short(components,width,height,datain,dataout,
element_size,ysize,group_size, myswap_bytes);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
if (!myswap_bytes)
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (*(const GLshort*)t +
*(const GLshort*)(t+group_size) +
*(const GLshort*)(t+ysize) +
*(const GLshort*)(t+ysize+group_size) + 2) / 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
else
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
GLushort b;
GLint buf;
b = __GLU_SWAP_2_BYTES(t);
buf = *(const GLshort*)&b;
b = __GLU_SWAP_2_BYTES(t+group_size);
buf += *(const GLshort*)&b;
b = __GLU_SWAP_2_BYTES(t+ysize);
buf += *(const GLshort*)&b;
b = __GLU_SWAP_2_BYTES(t+ysize+group_size);
buf += *(const GLshort*)&b;
s[0] = (GLshort)((buf+2)/4);
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
static void halve1Dimage_short(GLint components, GLuint width, GLuint height,
const GLshort *dataIn, GLshort *dataOut,
GLint element_size, GLint ysize,
GLint group_size, GLint myswap_bytes)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLshort *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLshort sshort[BOX2];
if (myswap_bytes) {
sshort[0]= __GLU_SWAP_2_BYTES(src);
sshort[1]= __GLU_SWAP_2_BYTES(src+group_size);
}
else {
sshort[0]= *(const GLshort*)src;
sshort[1]= *(const GLshort*)(src+group_size);
}
 
*dest= (sshort[0] + sshort[1]) / 2;
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLshort sshort[BOX2];
if (myswap_bytes) {
sshort[0]= __GLU_SWAP_2_BYTES(src);
sshort[1]= __GLU_SWAP_2_BYTES(src+ysize);
}
else {
sshort[0]= *(const GLshort*)src;
sshort[1]= *(const GLshort*)(src+ysize);
}
*dest= (sshort[0] + sshort[1]) / 2;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
}
 
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
 
} /* halve1Dimage_short() */
 
 
static void halveImage_uint(GLint components, GLuint width, GLuint height,
const GLuint *datain, GLuint *dataout,
GLint element_size, GLint ysize, GLint group_size,
GLint myswap_bytes)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLuint *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_uint(components,width,height,datain,dataout,
element_size,ysize,group_size, myswap_bytes);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
if (!myswap_bytes)
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
/* need to cast to double to hold large unsigned ints */
s[0] = ((double)*(const GLuint*)t +
(double)*(const GLuint*)(t+group_size) +
(double)*(const GLuint*)(t+ysize) +
(double)*(const GLuint*)(t+ysize+group_size))/4 + 0.5;
s++; t += element_size;
 
}
t += group_size;
}
t += padBytes;
t += ysize;
}
else
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
/* need to cast to double to hold large unsigned ints */
GLdouble buf;
buf = (GLdouble)__GLU_SWAP_4_BYTES(t) +
(GLdouble)__GLU_SWAP_4_BYTES(t+group_size) +
(GLdouble)__GLU_SWAP_4_BYTES(t+ysize) +
(GLdouble)__GLU_SWAP_4_BYTES(t+ysize+group_size);
s[0] = (GLuint)(buf/4 + 0.5);
 
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
/* */
static void halve1Dimage_uint(GLint components, GLuint width, GLuint height,
const GLuint *dataIn, GLuint *dataOut,
GLint element_size, GLint ysize,
GLint group_size, GLint myswap_bytes)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLuint *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLuint uint[BOX2];
if (myswap_bytes) {
uint[0]= __GLU_SWAP_4_BYTES(src);
uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
}
else {
uint[0]= *(const GLuint*)src;
uint[1]= *(const GLuint*)(src+group_size);
}
*dest= ((double)uint[0]+(double)uint[1])/2.0;
 
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLuint uint[BOX2];
if (myswap_bytes) {
uint[0]= __GLU_SWAP_4_BYTES(src);
uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
}
else {
uint[0]= *(const GLuint*)src;
uint[1]= *(const GLuint*)(src+ysize);
}
*dest= ((double)uint[0]+(double)uint[1])/2.0;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
}
 
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
 
} /* halve1Dimage_uint() */
 
static void halveImage_int(GLint components, GLuint width, GLuint height,
const GLint *datain, GLint *dataout, GLint element_size,
GLint ysize, GLint group_size, GLint myswap_bytes)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLint *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_int(components,width,height,datain,dataout,
element_size,ysize,group_size, myswap_bytes);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
if (!myswap_bytes)
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = ((float)*(const GLint*)t +
(float)*(const GLint*)(t+group_size) +
(float)*(const GLint*)(t+ysize) +
(float)*(const GLint*)(t+ysize+group_size))/4 + 0.5;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
else
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
GLuint b;
GLfloat buf;
b = __GLU_SWAP_4_BYTES(t);
buf = *(GLint*)&b;
b = __GLU_SWAP_4_BYTES(t+group_size);
buf += *(GLint*)&b;
b = __GLU_SWAP_4_BYTES(t+ysize);
buf += *(GLint*)&b;
b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
buf += *(GLint*)&b;
s[0] = (GLint)(buf/4 + 0.5);
 
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
/* */
static void halve1Dimage_int(GLint components, GLuint width, GLuint height,
const GLint *dataIn, GLint *dataOut,
GLint element_size, GLint ysize,
GLint group_size, GLint myswap_bytes)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLint *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLuint uint[BOX2];
if (myswap_bytes) {
uint[0]= __GLU_SWAP_4_BYTES(src);
uint[1]= __GLU_SWAP_4_BYTES(src+group_size);
}
else {
uint[0]= *(const GLuint*)src;
uint[1]= *(const GLuint*)(src+group_size);
}
*dest= ((float)uint[0]+(float)uint[1])/2.0;
 
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLuint uint[BOX2];
if (myswap_bytes) {
uint[0]= __GLU_SWAP_4_BYTES(src);
uint[1]= __GLU_SWAP_4_BYTES(src+ysize);
}
else {
uint[0]= *(const GLuint*)src;
uint[1]= *(const GLuint*)(src+ysize);
}
*dest= ((float)uint[0]+(float)uint[1])/2.0;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize;
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
}
 
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
 
} /* halve1Dimage_int() */
 
 
static void halveImage_float(GLint components, GLuint width, GLuint height,
const GLfloat *datain, GLfloat *dataout,
GLint element_size, GLint ysize, GLint group_size,
GLint myswap_bytes)
{
int i, j, k;
int newwidth, newheight;
int padBytes;
GLfloat *s;
const char *t;
 
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert( !(width == 1 && height == 1) ); /* can't be 1x1 */
halve1Dimage_float(components,width,height,datain,dataout,
element_size,ysize,group_size, myswap_bytes);
return;
}
 
newwidth = width / 2;
newheight = height / 2;
padBytes = ysize - (width*group_size);
s = dataout;
t = (const char *)datain;
 
/* Piece o' cake! */
if (!myswap_bytes)
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
s[0] = (*(const GLfloat*)t +
*(const GLfloat*)(t+group_size) +
*(const GLfloat*)(t+ysize) +
*(const GLfloat*)(t+ysize+group_size)) / 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
else
for (i = 0; i < newheight; i++) {
for (j = 0; j < newwidth; j++) {
for (k = 0; k < components; k++) {
union { GLuint b; GLfloat f; } swapbuf;
swapbuf.b = __GLU_SWAP_4_BYTES(t);
s[0] = swapbuf.f;
swapbuf.b = __GLU_SWAP_4_BYTES(t+group_size);
s[0] += swapbuf.f;
swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize);
s[0] += swapbuf.f;
swapbuf.b = __GLU_SWAP_4_BYTES(t+ysize+group_size);
s[0] += swapbuf.f;
s[0] /= 4;
s++; t += element_size;
}
t += group_size;
}
t += padBytes;
t += ysize;
}
}
 
/* */
static void halve1Dimage_float(GLint components, GLuint width, GLuint height,
const GLfloat *dataIn, GLfloat *dataOut,
GLint element_size, GLint ysize,
GLint group_size, GLint myswap_bytes)
{
GLint halfWidth= width / 2;
GLint halfHeight= height / 2;
const char *src= (const char *) dataIn;
GLfloat *dest= dataOut;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
for (jj= 0; jj< halfWidth; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLfloat sfloat[BOX2];
if (myswap_bytes) {
sfloat[0]= __GLU_SWAP_4_BYTES(src);
sfloat[1]= __GLU_SWAP_4_BYTES(src+group_size);
}
else {
sfloat[0]= *(const GLfloat*)src;
sfloat[1]= *(const GLfloat*)(src+group_size);
}
 
*dest= (sfloat[0] + sfloat[1]) / 2.0;
src+= element_size;
dest++;
}
src+= group_size; /* skip to next 2 */
}
{
int padBytes= ysize - (width*group_size);
src+= padBytes; /* for assertion only */
}
}
else if (width == 1) { /* 1 column */
int padBytes= ysize - (width * group_size);
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
int kk;
for (kk= 0; kk< components; kk++) {
#define BOX2 2
GLfloat sfloat[BOX2];
if (myswap_bytes) {
sfloat[0]= __GLU_SWAP_4_BYTES(src);
sfloat[1]= __GLU_SWAP_4_BYTES(src+ysize);
}
else {
sfloat[0]= *(const GLfloat*)src;
sfloat[1]= *(const GLfloat*)(src+ysize);
}
*dest= (sfloat[0] + sfloat[1]) / 2.0;
 
src+= element_size;
dest++;
}
src+= padBytes; /* add pad bytes, if any, to get to end to row */
src+= ysize; /* skip to odd row */
}
}
 
assert(src == &((const char *)dataIn)[ysize*height]);
assert((char *)dest == &((char *)dataOut)
[components * element_size * halfWidth * halfHeight]);
} /* halve1Dimage_float() */
 
static void scale_internal(GLint components, GLint widthin, GLint heightin,
const GLushort *datain,
GLint widthout, GLint heightout,
GLushort *dataout)
{
float x, lowx, highx, convx, halfconvx;
float y, lowy, highy, convy, halfconvy;
float xpercent,ypercent;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,yint,xint,xindex,yindex;
int temp;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage(components, widthin, heightin, datain, dataout);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
halfconvx = convx/2;
halfconvy = convy/2;
for (i = 0; i < heightout; i++) {
y = convy * (i+0.5);
if (heightin > heightout) {
highy = y + halfconvy;
lowy = y - halfconvy;
} else {
highy = y + 0.5;
lowy = y - 0.5;
}
for (j = 0; j < widthout; j++) {
x = convx * (j+0.5);
if (widthin > widthout) {
highx = x + halfconvx;
lowx = x - halfconvx;
} else {
highx = x + 0.5;
lowx = x - 0.5;
}
 
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
area = 0.0;
 
y = lowy;
yint = floor(y);
while (y < highy) {
yindex = (yint + heightin) % heightin;
if (highy < yint+1) {
ypercent = highy - y;
} else {
ypercent = yint+1 - y;
}
 
x = lowx;
xint = floor(x);
 
while (x < highx) {
xindex = (xint + widthin) % widthin;
if (highx < xint+1) {
xpercent = highx - x;
} else {
xpercent = xint+1 - x;
}
 
percent = xpercent * ypercent;
area += percent;
temp = (xindex + (yindex * widthin)) * components;
for (k = 0; k < components; k++) {
totals[k] += datain[temp + k] * percent;
}
 
xint++;
x = xint;
}
yint++;
y = yint;
}
 
temp = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
/* totals[] should be rounded in the case of enlarging an RGB
* ramp when the type is 332 or 4444
*/
dataout[temp + k] = (totals[k]+0.5)/area;
}
}
}
}
 
static void scale_internal_ubyte(GLint components, GLint widthin,
GLint heightin, const GLubyte *datain,
GLint widthout, GLint heightout,
GLubyte *dataout, GLint element_size,
GLint ysize, GLint group_size)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_ubyte(components, widthin, heightin,
(const GLubyte *)datain, (GLubyte *)dataout,
element_size, ysize, group_size);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
 
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
 
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
totals[k] += (GLubyte)(*(left))*(1-lowx_float)
+(GLubyte)(*(right))*highx_float;
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * x_percent;
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index)) * percent;
}
}
 
 
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLubyte)(*(temp_index));
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
static void scale_internal_byte(GLint components, GLint widthin,
GLint heightin, const GLbyte *datain,
GLint widthout, GLint heightout,
GLbyte *dataout, GLint element_size,
GLint ysize, GLint group_size)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_byte(components, widthin, heightin,
(const GLbyte *)datain, (GLbyte *)dataout,
element_size, ysize, group_size);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
 
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
 
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
totals[k] += (GLbyte)(*(left))*(1-lowx_float)
+(GLbyte)(*(right))*highx_float;
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * x_percent;
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * y_percent;
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index)) * percent;
}
}
 
 
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
totals[k] += (GLbyte)(*(temp_index));
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
static void scale_internal_ushort(GLint components, GLint widthin,
GLint heightin, const GLushort *datain,
GLint widthout, GLint heightout,
GLushort *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_ushort(components, widthin, heightin,
(const GLushort *)datain, (GLushort *)dataout,
element_size, ysize, group_size, myswap_bytes);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
__GLU_SWAP_2_BYTES(right) * highx_float;
} else {
totals[k] += *(const GLushort*)left * (1-lowx_float)
+ *(const GLushort*)right * highx_float;
}
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * x_percent;
} else {
totals[k] += *(const GLushort*)temp_index * x_percent;
}
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
}
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index);
} else {
totals[k] += *(const GLushort*)temp_index;
}
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
static void scale_internal_short(GLint components, GLint widthin,
GLint heightin, const GLshort *datain,
GLint widthout, GLint heightout,
GLshort *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
GLushort swapbuf; /* unsigned buffer */
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_short(components, widthin, heightin,
(const GLshort *)datain, (GLshort *)dataout,
element_size, ysize, group_size, myswap_bytes);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLshort*)temp_index * y_percent;
}
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLshort*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(left);
totals[k] += *(const GLshort*)&swapbuf * (1-lowx_float);
swapbuf = __GLU_SWAP_2_BYTES(right);
totals[k] += *(const GLshort*)&swapbuf * highx_float;
} else {
totals[k] += *(const GLshort*)left * (1-lowx_float)
+ *(const GLshort*)right * highx_float;
}
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * x_percent;
} else {
totals[k] += *(const GLshort*)temp_index * x_percent;
}
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
 
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLshort*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf * percent;
} else {
totals[k] += *(const GLshort*)temp_index * percent;
}
}
}
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_2_BYTES(temp_index);
totals[k] += *(const GLshort*)&swapbuf;
} else {
totals[k] += *(const GLshort*)temp_index;
}
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
static void scale_internal_uint(GLint components, GLint widthin,
GLint heightin, const GLuint *datain,
GLint widthout, GLint heightout,
GLuint *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_uint(components, widthin, heightin,
(const GLuint *)datain, (GLuint *)dataout,
element_size, ysize, group_size, myswap_bytes);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_4_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLuint*)temp_index * y_percent;
}
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_4_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLuint*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_4_BYTES(left) * (1-lowx_float)
+ __GLU_SWAP_4_BYTES(right) * highx_float;
} else {
totals[k] += *(const GLuint*)left * (1-lowx_float)
+ *(const GLuint*)right * highx_float;
}
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_4_BYTES(temp_index) * x_percent;
} else {
totals[k] += *(const GLuint*)temp_index * x_percent;
}
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
 
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_4_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLuint*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLuint*)temp_index * percent;
}
}
}
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_4_BYTES(temp_index);
} else {
totals[k] += *(const GLuint*)temp_index;
}
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
/* clamp at UINT_MAX */
float value= totals[k]/area;
if (value >= (float) UINT_MAX) { /* need '=' */
dataout[outindex + k] = UINT_MAX;
}
else dataout[outindex + k] = value;
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
 
 
static void scale_internal_int(GLint components, GLint widthin,
GLint heightin, const GLint *datain,
GLint widthout, GLint heightout,
GLint *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
GLuint swapbuf; /* unsigned buffer */
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_int(components, widthin, heightin,
(const GLint *)datain, (GLint *)dataout,
element_size, ysize, group_size, myswap_bytes);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLint*)temp_index * y_percent;
}
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLint*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(left);
totals[k] += *(const GLint*)&swapbuf * (1-lowx_float);
swapbuf = __GLU_SWAP_4_BYTES(right);
totals[k] += *(const GLint*)&swapbuf * highx_float;
} else {
totals[k] += *(const GLint*)left * (1-lowx_float)
+ *(const GLint*)right * highx_float;
}
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * x_percent;
} else {
totals[k] += *(const GLint*)temp_index * x_percent;
}
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
 
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * y_percent;
} else {
totals[k] += *(const GLint*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf * percent;
} else {
totals[k] += *(const GLint*)temp_index * percent;
}
}
}
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += *(const GLint*)&swapbuf;
} else {
totals[k] += *(const GLint*)temp_index;
}
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
 
 
static void scale_internal_float(GLint components, GLint widthin,
GLint heightin, const GLfloat *datain,
GLint widthout, GLint heightout,
GLfloat *dataout, GLint element_size,
GLint ysize, GLint group_size,
GLint myswap_bytes)
{
float convx;
float convy;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
const char *temp_index;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
union { GLuint b; GLfloat f; } swapbuf;
 
if (widthin == widthout*2 && heightin == heightout*2) {
halveImage_float(components, widthin, heightin,
(const GLfloat *)datain, (GLfloat *)dataout,
element_size, ysize, group_size, myswap_bytes);
return;
}
convy = (float) heightin/heightout;
convx = (float) widthin/widthout;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightout; i++) {
/* Clamp here to be sure we don't read beyond input buffer. */
if (highy_int >= heightin)
highy_int = heightin - 1;
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthout; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*group_size;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)datain + xindex + lowy_int * ysize;
percent = y_percent * (1-lowx_float);
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * y_percent;
} else {
totals[k] += *(const GLfloat*)temp_index * y_percent;
}
}
}
temp += group_size;
right = temp;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)datain + xindex + highy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
for(l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * y_percent;
} else {
totals[k] += *(const GLfloat*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += ysize;
right += ysize;
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(left);
totals[k] += swapbuf.f * (1-lowx_float);
swapbuf.b = __GLU_SWAP_4_BYTES(right);
totals[k] += swapbuf.f * highx_float;
} else {
totals[k] += *(const GLfloat*)left * (1-lowx_float)
+ *(const GLfloat*)right * highx_float;
}
}
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
for(m = lowy_int+1; m < highy_int; m++) {
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * x_percent;
} else {
totals[k] += *(const GLfloat*)temp_index * x_percent;
}
}
}
percent = x_percent * highy_float;
temp += ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
 
temp = (const char *)datain + xindex + lowy_int*ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
for (l = lowx_int+1; l < highx_int; l++) {
temp += group_size;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * y_percent;
} else {
totals[k] += *(const GLfloat*)temp_index * y_percent;
}
}
}
temp += group_size;
percent = y_percent * highx_float;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)datain + xindex + lowy_int * ysize;
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f * percent;
} else {
totals[k] += *(const GLfloat*)temp_index * percent;
}
}
}
 
/* this is for the pixels in the body */
temp0 = (const char *)datain + xindex + group_size +
(lowy_int+1)*ysize;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
swapbuf.b = __GLU_SWAP_4_BYTES(temp_index);
totals[k] += swapbuf.f;
} else {
totals[k] += *(const GLfloat*)temp_index;
}
}
temp += group_size;
}
temp0 += ysize;
}
 
outindex = (j + (i * widthout)) * components;
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
}
 
static int checkMipmapArgs(GLenum internalFormat, GLenum format, GLenum type)
{
if (!legalFormat(format) || !legalType(type)) {
return GLU_INVALID_ENUM;
}
if (format == GL_STENCIL_INDEX) {
return GLU_INVALID_ENUM;
}
 
if (!isLegalFormatForPackedPixelType(format, type)) {
return GLU_INVALID_OPERATION;
}
 
return 0;
} /* checkMipmapArgs() */
 
static GLboolean legalFormat(GLenum format)
{
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_RGB:
case GL_RGBA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_BGR:
case GL_BGRA:
return GL_TRUE;
default:
return GL_FALSE;
}
}
 
 
static GLboolean legalType(GLenum type)
{
switch(type) {
case GL_BITMAP:
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
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_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:
return GL_TRUE;
default:
return GL_FALSE;
}
}
 
/* */
static GLboolean isTypePackedPixel(GLenum type)
{
assert(legalType(type));
 
if (type == GL_UNSIGNED_BYTE_3_3_2 ||
type == GL_UNSIGNED_BYTE_2_3_3_REV ||
type == GL_UNSIGNED_SHORT_5_6_5 ||
type == GL_UNSIGNED_SHORT_5_6_5_REV ||
type == GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
type == GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL_UNSIGNED_INT_8_8_8_8 ||
type == GL_UNSIGNED_INT_8_8_8_8_REV ||
type == GL_UNSIGNED_INT_10_10_10_2 ||
type == GL_UNSIGNED_INT_2_10_10_10_REV) {
return 1;
}
else return 0;
} /* isTypePackedPixel() */
 
/* Determines if the packed pixel type is compatible with the format */
static GLboolean isLegalFormatForPackedPixelType(GLenum format, GLenum type)
{
/* if not a packed pixel type then return true */
if (!isTypePackedPixel(type)) {
return GL_TRUE;
}
 
/* 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB */
if ((type == GL_UNSIGNED_BYTE_3_3_2 || type == GL_UNSIGNED_BYTE_2_3_3_REV||
type == GL_UNSIGNED_SHORT_5_6_5|| type == GL_UNSIGNED_SHORT_5_6_5_REV)
&& format != GL_RGB)
return GL_FALSE;
 
/* 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV &
* 10_10_10_2/2_10_10_10_REV are only compatible with RGBA, BGRA & ABGR_EXT.
*/
if ((type == GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
type == GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL_UNSIGNED_INT_8_8_8_8 ||
type == GL_UNSIGNED_INT_8_8_8_8_REV ||
type == GL_UNSIGNED_INT_10_10_10_2 ||
type == GL_UNSIGNED_INT_2_10_10_10_REV) &&
(format != GL_RGBA &&
format != GL_BGRA)) {
return GL_FALSE;
}
 
return GL_TRUE;
} /* isLegalFormatForPackedPixelType() */
 
static GLboolean isLegalLevels(GLint userLevel,GLint baseLevel,GLint maxLevel,
GLint totalLevels)
{
if (baseLevel < 0 || baseLevel < userLevel || maxLevel < baseLevel ||
totalLevels < maxLevel)
return GL_FALSE;
else return GL_TRUE;
} /* isLegalLevels() */
 
/* Given user requested texture size, determine if it fits. If it
* doesn't then halve both sides and make the determination again
* until it does fit (for IR only).
* Note that proxy textures are not implemented in RE* even though
* they advertise the texture extension.
* Note that proxy textures are implemented but not according to spec in
* IMPACT*.
*/
static void closestFit(GLenum target, GLint width, GLint height,
GLint internalFormat, GLenum format, GLenum type,
GLint *newWidth, GLint *newHeight)
{
/* Use proxy textures if OpenGL version is >= 1.1 */
if ( (strtod((const char *)glGetString(GL_VERSION),NULL) >= 1.1)
) {
GLint widthPowerOf2= nearestPower(width);
GLint heightPowerOf2= nearestPower(height);
GLint proxyWidth;
 
do {
/* compute level 1 width & height, clamping each at 1 */
GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
widthPowerOf2 >> 1 :
widthPowerOf2;
GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
heightPowerOf2 >> 1 :
heightPowerOf2;
GLenum proxyTarget;
assert(widthAtLevelOne > 0); assert(heightAtLevelOne > 0);
 
/* does width x height at level 1 & all their mipmaps fit? */
if (target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D) {
proxyTarget = GL_PROXY_TEXTURE_2D;
glTexImage2D(proxyTarget, 1, /* must be non-zero */
internalFormat,
widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
} else
#if defined(GL_ARB_texture_cube_map)
if ((target == GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB) ||
(target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB) ||
(target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB) ||
(target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB) ||
(target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB) ||
(target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
proxyTarget = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
glTexImage2D(proxyTarget, 1, /* must be non-zero */
internalFormat,
widthAtLevelOne,heightAtLevelOne,0,format,type,NULL);
} else
#endif /* GL_ARB_texture_cube_map */
{
assert(target == GL_TEXTURE_1D || target == GL_PROXY_TEXTURE_1D);
proxyTarget = GL_PROXY_TEXTURE_1D;
glTexImage1D(proxyTarget, 1, /* must be non-zero */
internalFormat,widthAtLevelOne,0,format,type,NULL);
}
glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
/* does it fit??? */
if (proxyWidth == 0) { /* nope, so try again with these sizes */
if (widthPowerOf2 == 1 && heightPowerOf2 == 1) {
/* An 1x1 texture couldn't fit for some reason, so
* break out. This should never happen. But things
* happen. The disadvantage with this if-statement is
* that we will never be aware of when this happens
* since it will silently branch out.
*/
goto noProxyTextures;
}
widthPowerOf2= widthAtLevelOne;
heightPowerOf2= heightAtLevelOne;
}
/* else it does fit */
} while (proxyWidth == 0);
/* loop must terminate! */
 
/* return the width & height at level 0 that fits */
*newWidth= widthPowerOf2;
*newHeight= heightPowerOf2;
/*printf("Proxy Textures\n");*/
} /* if gluCheckExtension() */
else { /* no texture extension, so do this instead */
GLint maxsize;
 
noProxyTextures:
 
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
/* clamp user's texture sizes to maximum sizes, if necessary */
*newWidth = nearestPower(width);
if (*newWidth > maxsize) *newWidth = maxsize;
*newHeight = nearestPower(height);
if (*newHeight > maxsize) *newHeight = maxsize;
/*printf("NO proxy textures\n");*/
}
} /* closestFit() */
 
GLint GLAPIENTRY
gluScaleImage(GLenum format, GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLsizei widthout, GLsizei heightout, GLenum typeout,
void *dataout)
{
int components;
GLushort *beforeImage;
GLushort *afterImage;
PixelStorageModes psm;
 
if (widthin == 0 || heightin == 0 || widthout == 0 || heightout == 0) {
return 0;
}
if (widthin < 0 || heightin < 0 || widthout < 0 || heightout < 0) {
return GLU_INVALID_VALUE;
}
if (!legalFormat(format) || !legalType(typein) || !legalType(typeout)) {
return GLU_INVALID_ENUM;
}
if (!isLegalFormatForPackedPixelType(format, typein)) {
return GLU_INVALID_OPERATION;
}
if (!isLegalFormatForPackedPixelType(format, typeout)) {
return GLU_INVALID_OPERATION;
}
beforeImage =
malloc(image_size(widthin, heightin, format, GL_UNSIGNED_SHORT));
afterImage =
malloc(image_size(widthout, heightout, format, GL_UNSIGNED_SHORT));
if (beforeImage == NULL || afterImage == NULL) {
free(beforeImage);
free(afterImage);
return GLU_OUT_OF_MEMORY;
}
 
retrieveStoreModes(&psm);
fill_image(&psm,widthin, heightin, format, typein, is_index(format),
datain, beforeImage);
components = elements_per_group(format, 0);
scale_internal(components, widthin, heightin, beforeImage,
widthout, heightout, afterImage);
empty_image(&psm,widthout, heightout, format, typeout,
is_index(format), afterImage, dataout);
free((GLbyte *) beforeImage);
free((GLbyte *) afterImage);
 
return 0;
}
 
int gluBuild1DMipmapLevelsCore(GLenum target, GLint internalFormat,
GLsizei width,
GLsizei widthPowerOf2,
GLenum format, GLenum type,
GLint userLevel, GLint baseLevel,GLint maxLevel,
const void *data)
{
GLint newwidth;
GLint level, levels;
GLushort *newImage;
GLint newImage_width;
GLushort *otherImage;
GLushort *imageTemp;
GLint memreq;
GLint cmpts;
PixelStorageModes psm;
 
assert(checkMipmapArgs(internalFormat,format,type) == 0);
assert(width >= 1);
 
otherImage = NULL;
 
newwidth= widthPowerOf2;
levels = computeLog(newwidth);
 
levels+= userLevel;
 
retrieveStoreModes(&psm);
newImage = (GLushort *)
malloc(image_size(width, 1, format, GL_UNSIGNED_SHORT));
newImage_width = width;
if (newImage == NULL) {
return GLU_OUT_OF_MEMORY;
}
fill_image(&psm,width, 1, format, type, is_index(format),
data, newImage);
cmpts = elements_per_group(format,type);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
/*
** If swap_bytes was set, swapping occurred in fill_image.
*/
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
 
for (level = userLevel; level <= levels; level++) {
if (newImage_width == newwidth) {
/* Use newImage for this level */
if (baseLevel <= level && level <= maxLevel) {
glTexImage1D(target, level, internalFormat, newImage_width,
0, format, GL_UNSIGNED_SHORT, (void *) newImage);
}
} else {
if (otherImage == NULL) {
memreq = image_size(newwidth, 1, format, GL_UNSIGNED_SHORT);
otherImage = (GLushort *) malloc(memreq);
if (otherImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
free(newImage);
return GLU_OUT_OF_MEMORY;
}
}
scale_internal(cmpts, newImage_width, 1, newImage,
newwidth, 1, otherImage);
/* Swap newImage and otherImage */
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
 
newImage_width = newwidth;
if (baseLevel <= level && level <= maxLevel) {
glTexImage1D(target, level, internalFormat, newImage_width,
0, format, GL_UNSIGNED_SHORT, (void *) newImage);
}
}
if (newwidth > 1) newwidth /= 2;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
 
free((GLbyte *) newImage);
if (otherImage) {
free((GLbyte *) otherImage);
}
return 0;
}
 
GLint GLAPIENTRY
gluBuild1DMipmapLevels(GLenum target, GLint internalFormat,
GLsizei width,
GLenum format, GLenum type,
GLint userLevel, GLint baseLevel, GLint maxLevel,
const void *data)
{
int levels;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1) {
return GLU_INVALID_VALUE;
}
 
levels = computeLog(width);
 
levels+= userLevel;
if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
return GLU_INVALID_VALUE;
 
return gluBuild1DMipmapLevelsCore(target, internalFormat,
width,
width,format, type,
userLevel, baseLevel, maxLevel,
data);
} /* gluBuild1DMipmapLevels() */
 
GLint GLAPIENTRY
gluBuild1DMipmaps(GLenum target, GLint internalFormat, GLsizei width,
GLenum format, GLenum type,
const void *data)
{
GLint widthPowerOf2;
int levels;
GLint dummy;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1) {
return GLU_INVALID_VALUE;
}
 
closestFit(target,width,1,internalFormat,format,type,&widthPowerOf2,&dummy);
levels = computeLog(widthPowerOf2);
 
return gluBuild1DMipmapLevelsCore(target,internalFormat,
width,
widthPowerOf2,
format,type,0,0,levels,data);
}
 
static int bitmapBuild2DMipmaps(GLenum target, GLint internalFormat,
GLint width, GLint height, GLenum format,
GLenum type, const void *data)
{
GLint newwidth, newheight;
GLint level, levels;
GLushort *newImage;
GLint newImage_width;
GLint newImage_height;
GLushort *otherImage;
GLushort *imageTemp;
GLint memreq;
GLint cmpts;
PixelStorageModes psm;
 
retrieveStoreModes(&psm);
 
#if 0
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
newwidth = nearestPower(width);
if (newwidth > maxsize) newwidth = maxsize;
newheight = nearestPower(height);
if (newheight > maxsize) newheight = maxsize;
#else
closestFit(target,width,height,internalFormat,format,type,
&newwidth,&newheight);
#endif
levels = computeLog(newwidth);
level = computeLog(newheight);
if (level > levels) levels=level;
 
otherImage = NULL;
newImage = (GLushort *)
malloc(image_size(width, height, format, GL_UNSIGNED_SHORT));
newImage_width = width;
newImage_height = height;
if (newImage == NULL) {
return GLU_OUT_OF_MEMORY;
}
 
fill_image(&psm,width, height, format, type, is_index(format),
data, newImage);
 
cmpts = elements_per_group(format,type);
glPixelStorei(GL_UNPACK_ALIGNMENT, 2);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
/*
** If swap_bytes was set, swapping occurred in fill_image.
*/
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
 
for (level = 0; level <= levels; level++) {
if (newImage_width == newwidth && newImage_height == newheight) { /* Use newImage for this level */
glTexImage2D(target, level, internalFormat, newImage_width,
newImage_height, 0, format, GL_UNSIGNED_SHORT,
(void *) newImage);
} else {
if (otherImage == NULL) {
memreq =
image_size(newwidth, newheight, format, GL_UNSIGNED_SHORT);
otherImage = (GLushort *) malloc(memreq);
if (otherImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS,psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
free(newImage);
return GLU_OUT_OF_MEMORY;
}
}
scale_internal(cmpts, newImage_width, newImage_height, newImage,
newwidth, newheight, otherImage);
/* Swap newImage and otherImage */
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
 
newImage_width = newwidth;
newImage_height = newheight;
glTexImage2D(target, level, internalFormat, newImage_width,
newImage_height, 0, format, GL_UNSIGNED_SHORT,
(void *) newImage);
}
if (newwidth > 1) newwidth /= 2;
if (newheight > 1) newheight /= 2;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
 
free((GLbyte *) newImage);
if (otherImage) {
free((GLbyte *) otherImage);
}
return 0;
}
 
/* To make swapping images less error prone */
#define __GLU_INIT_SWAP_IMAGE void *tmpImage
#define __GLU_SWAP_IMAGE(a,b) tmpImage = a; a = b; b = tmpImage;
 
static int gluBuild2DMipmapLevelsCore(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height,
GLsizei widthPowerOf2,
GLsizei heightPowerOf2,
GLenum format, GLenum type,
GLint userLevel,
GLint baseLevel,GLint maxLevel,
const void *data)
{
GLint newwidth, newheight;
GLint level, levels;
const void *usersImage; /* passed from user. Don't touch! */
void *srcImage, *dstImage; /* scratch area to build mipmapped images */
__GLU_INIT_SWAP_IMAGE;
GLint memreq;
GLint cmpts;
 
GLint myswap_bytes, groups_per_line, element_size, group_size;
GLint rowsize, padding;
PixelStorageModes psm;
 
assert(checkMipmapArgs(internalFormat,format,type) == 0);
assert(width >= 1 && height >= 1);
 
if(type == GL_BITMAP) {
return bitmapBuild2DMipmaps(target, internalFormat, width, height,
format, type, data);
}
 
srcImage = dstImage = NULL;
 
newwidth= widthPowerOf2;
newheight= heightPowerOf2;
levels = computeLog(newwidth);
level = computeLog(newheight);
if (level > levels) levels=level;
 
levels+= userLevel;
 
retrieveStoreModes(&psm);
myswap_bytes = psm.unpack_swap_bytes;
cmpts = elements_per_group(format,type);
if (psm.unpack_row_length > 0) {
groups_per_line = psm.unpack_row_length;
} else {
groups_per_line = width;
}
 
element_size = bytes_per_element(type);
group_size = element_size * cmpts;
if (element_size == 1) myswap_bytes = 0;
 
rowsize = groups_per_line * group_size;
padding = (rowsize % psm.unpack_alignment);
if (padding) {
rowsize += psm.unpack_alignment - padding;
}
usersImage = (const GLubyte *) data + psm.unpack_skip_rows * rowsize +
psm.unpack_skip_pixels * group_size;
 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
 
level = userLevel;
 
/* already power-of-two square */
if (width == newwidth && height == newheight) {
/* Use usersImage for level userLevel */
if (baseLevel <= level && level <= maxLevel) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glTexImage2D(target, level, internalFormat, width,
height, 0, format, type,
usersImage);
}
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
if(levels == 0) { /* we're done. clean up and return */
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
return 0;
}
{
int nextWidth= newwidth/2;
int nextHeight= newheight/2;
 
/* clamp to 1 */
if (nextWidth < 1) nextWidth= 1;
if (nextHeight < 1) nextHeight= 1;
memreq = image_size(nextWidth, nextHeight, format, type);
}
 
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memreq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memreq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memreq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memreq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memreq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memreq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memreq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memreq);
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:
dstImage = (GLushort *)malloc(memreq);
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:
dstImage = (GLuint *)malloc(memreq);
break;
default:
return GLU_INVALID_ENUM;
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
return GLU_OUT_OF_MEMORY;
}
else
switch(type) {
case GL_UNSIGNED_BYTE:
halveImage_ubyte(cmpts, width, height,
(const GLubyte *)usersImage, (GLubyte *)dstImage,
element_size, rowsize, group_size);
break;
case GL_BYTE:
halveImage_byte(cmpts, width, height,
(const GLbyte *)usersImage, (GLbyte *)dstImage,
element_size, rowsize, group_size);
break;
case GL_UNSIGNED_SHORT:
halveImage_ushort(cmpts, width, height,
(const GLushort *)usersImage, (GLushort *)dstImage,
element_size, rowsize, group_size, myswap_bytes);
break;
case GL_SHORT:
halveImage_short(cmpts, width, height,
(const GLshort *)usersImage, (GLshort *)dstImage,
element_size, rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_INT:
halveImage_uint(cmpts, width, height,
(const GLuint *)usersImage, (GLuint *)dstImage,
element_size, rowsize, group_size, myswap_bytes);
break;
case GL_INT:
halveImage_int(cmpts, width, height,
(const GLint *)usersImage, (GLint *)dstImage,
element_size, rowsize, group_size, myswap_bytes);
break;
case GL_FLOAT:
halveImage_float(cmpts, width, height,
(const GLfloat *)usersImage, (GLfloat *)dstImage,
element_size, rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_BYTE_3_3_2:
assert(format == GL_RGB);
halveImagePackedPixel(3,extract332,shove332,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
assert(format == GL_RGB);
halveImagePackedPixel(3,extract233rev,shove233rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5:
halveImagePackedPixel(3,extract565,shove565,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
halveImagePackedPixel(3,extract565rev,shove565rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
halveImagePackedPixel(4,extract4444,shove4444,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
halveImagePackedPixel(4,extract4444rev,shove4444rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
halveImagePackedPixel(4,extract5551,shove5551,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
halveImagePackedPixel(4,extract1555rev,shove1555rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8:
halveImagePackedPixel(4,extract8888,shove8888,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
halveImagePackedPixel(4,extract8888rev,shove8888rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_10_10_10_2:
halveImagePackedPixel(4,extract1010102,shove1010102,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
width,height,usersImage,dstImage,
element_size,rowsize,myswap_bytes);
break;
default:
assert(0);
break;
}
newwidth = width/2;
newheight = height/2;
/* clamp to 1 */
if (newwidth < 1) newwidth= 1;
if (newheight < 1) newheight= 1;
 
myswap_bytes = 0;
rowsize = newwidth * group_size;
memreq = image_size(newwidth, newheight, format, type);
/* Swap srcImage and dstImage */
__GLU_SWAP_IMAGE(srcImage,dstImage);
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memreq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memreq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memreq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memreq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memreq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memreq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memreq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memreq);
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:
dstImage = (GLushort *)malloc(memreq);
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:
dstImage = (GLuint *)malloc(memreq);
break;
default:
return GLU_INVALID_ENUM;
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
free(srcImage);
return GLU_OUT_OF_MEMORY;
}
/* level userLevel+1 is in srcImage; level userLevel already saved */
level = userLevel+1;
} else { /* user's image is *not* nice power-of-2 sized square */
memreq = image_size(newwidth, newheight, format, type);
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memreq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memreq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memreq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memreq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memreq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memreq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memreq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memreq);
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:
dstImage = (GLushort *)malloc(memreq);
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:
dstImage = (GLuint *)malloc(memreq);
break;
default:
return GLU_INVALID_ENUM;
}
 
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
return GLU_OUT_OF_MEMORY;
}
 
switch(type) {
case GL_UNSIGNED_BYTE:
scale_internal_ubyte(cmpts, width, height,
(const GLubyte *)usersImage, newwidth, newheight,
(GLubyte *)dstImage, element_size,
rowsize, group_size);
break;
case GL_BYTE:
scale_internal_byte(cmpts, width, height,
(const GLbyte *)usersImage, newwidth, newheight,
(GLbyte *)dstImage, element_size,
rowsize, group_size);
break;
case GL_UNSIGNED_SHORT:
scale_internal_ushort(cmpts, width, height,
(const GLushort *)usersImage, newwidth, newheight,
(GLushort *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_SHORT:
scale_internal_short(cmpts, width, height,
(const GLshort *)usersImage, newwidth, newheight,
(GLshort *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_INT:
scale_internal_uint(cmpts, width, height,
(const GLuint *)usersImage, newwidth, newheight,
(GLuint *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_INT:
scale_internal_int(cmpts, width, height,
(const GLint *)usersImage, newwidth, newheight,
(GLint *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_FLOAT:
scale_internal_float(cmpts, width, height,
(const GLfloat *)usersImage, newwidth, newheight,
(GLfloat *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_BYTE_3_3_2:
scaleInternalPackedPixel(3,extract332,shove332,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
scaleInternalPackedPixel(3,extract233rev,shove233rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5:
scaleInternalPackedPixel(3,extract565,shove565,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
scaleInternalPackedPixel(3,extract565rev,shove565rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
scaleInternalPackedPixel(4,extract4444,shove4444,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
scaleInternalPackedPixel(4,extract4444rev,shove4444rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
scaleInternalPackedPixel(4,extract5551,shove5551,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
scaleInternalPackedPixel(4,extract1555rev,shove1555rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8:
scaleInternalPackedPixel(4,extract8888,shove8888,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
scaleInternalPackedPixel(4,extract8888rev,shove8888rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_10_10_10_2:
scaleInternalPackedPixel(4,extract1010102,shove1010102,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
scaleInternalPackedPixel(4,extract2101010rev,shove2101010rev,
width, height,usersImage,
newwidth,newheight,(void *)dstImage,
element_size,rowsize,myswap_bytes);
break;
default:
assert(0);
break;
}
myswap_bytes = 0;
rowsize = newwidth * group_size;
/* Swap dstImage and srcImage */
__GLU_SWAP_IMAGE(srcImage,dstImage);
 
if(levels != 0) { /* use as little memory as possible */
{
int nextWidth= newwidth/2;
int nextHeight= newheight/2;
if (nextWidth < 1) nextWidth= 1;
if (nextHeight < 1) nextHeight= 1;
 
memreq = image_size(nextWidth, nextHeight, format, type);
}
 
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memreq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memreq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memreq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memreq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memreq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memreq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memreq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memreq);
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:
dstImage = (GLushort *)malloc(memreq);
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:
dstImage = (GLuint *)malloc(memreq);
break;
default:
return GLU_INVALID_ENUM;
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
free(srcImage);
return GLU_OUT_OF_MEMORY;
}
}
/* level userLevel is in srcImage; nothing saved yet */
level = userLevel;
}
 
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
if (baseLevel <= level && level <= maxLevel) {
glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
format, type, (void *)srcImage);
}
 
level++; /* update current level for the loop */
for (; level <= levels; level++) {
switch(type) {
case GL_UNSIGNED_BYTE:
halveImage_ubyte(cmpts, newwidth, newheight,
(GLubyte *)srcImage, (GLubyte *)dstImage, element_size,
rowsize, group_size);
break;
case GL_BYTE:
halveImage_byte(cmpts, newwidth, newheight,
(GLbyte *)srcImage, (GLbyte *)dstImage, element_size,
rowsize, group_size);
break;
case GL_UNSIGNED_SHORT:
halveImage_ushort(cmpts, newwidth, newheight,
(GLushort *)srcImage, (GLushort *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_SHORT:
halveImage_short(cmpts, newwidth, newheight,
(GLshort *)srcImage, (GLshort *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_INT:
halveImage_uint(cmpts, newwidth, newheight,
(GLuint *)srcImage, (GLuint *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_INT:
halveImage_int(cmpts, newwidth, newheight,
(GLint *)srcImage, (GLint *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_FLOAT:
halveImage_float(cmpts, newwidth, newheight,
(GLfloat *)srcImage, (GLfloat *)dstImage, element_size,
rowsize, group_size, myswap_bytes);
break;
case GL_UNSIGNED_BYTE_3_3_2:
halveImagePackedPixel(3,extract332,shove332,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
halveImagePackedPixel(3,extract233rev,shove233rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5:
halveImagePackedPixel(3,extract565,shove565,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
halveImagePackedPixel(3,extract565rev,shove565rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
halveImagePackedPixel(4,extract4444,shove4444,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
halveImagePackedPixel(4,extract4444rev,shove4444rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
halveImagePackedPixel(4,extract5551,shove5551,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
halveImagePackedPixel(4,extract1555rev,shove1555rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8:
halveImagePackedPixel(4,extract8888,shove8888,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
halveImagePackedPixel(4,extract8888rev,shove8888rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_INT_10_10_10_2:
halveImagePackedPixel(4,extract1010102,shove1010102,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
halveImagePackedPixel(4,extract2101010rev,shove2101010rev,
newwidth,newheight,
srcImage,dstImage,element_size,rowsize,
myswap_bytes);
break;
default:
assert(0);
break;
}
 
__GLU_SWAP_IMAGE(srcImage,dstImage);
 
if (newwidth > 1) { newwidth /= 2; rowsize /= 2;}
if (newheight > 1) newheight /= 2;
{
/* compute amount to pad per row, if any */
int rowPad= rowsize % psm.unpack_alignment;
 
/* should row be padded? */
if (rowPad == 0) { /* nope, row should not be padded */
/* call tex image with srcImage untouched since it's not padded */
if (baseLevel <= level && level <= maxLevel) {
glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
format, type, (void *) srcImage);
}
}
else { /* yes, row should be padded */
/* compute length of new row in bytes, including padding */
int newRowLength= rowsize + psm.unpack_alignment - rowPad;
int ii; unsigned char *dstTrav, *srcTrav; /* indices for copying */
 
/* allocate new image for mipmap of size newRowLength x newheight */
void *newMipmapImage= malloc((size_t) (newRowLength*newheight));
if (newMipmapImage == NULL) {
/* out of memory so return */
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
return GLU_OUT_OF_MEMORY;
}
 
/* copy image from srcImage into newMipmapImage by rows */
for (ii= 0,
dstTrav= (unsigned char *) newMipmapImage,
srcTrav= (unsigned char *) srcImage;
ii< newheight;
ii++,
dstTrav+= newRowLength, /* make sure the correct distance... */
srcTrav+= rowsize) { /* ...is skipped */
memcpy(dstTrav,srcTrav,rowsize);
/* note that the pad bytes are not visited and will contain
* garbage, which is ok.
*/
}
 
/* ...and use this new image for mipmapping instead */
if (baseLevel <= level && level <= maxLevel) {
glTexImage2D(target, level, internalFormat, newwidth, newheight, 0,
format, type, newMipmapImage);
}
free(newMipmapImage); /* don't forget to free it! */
} /* else */
}
} /* for level */
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
 
free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
if (dstImage) { /* if it's non-rectangular and only 1 level */
free(dstImage);
}
return 0;
} /* gluBuild2DMipmapLevelsCore() */
 
GLint GLAPIENTRY
gluBuild2DMipmapLevels(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
GLint userLevel, GLint baseLevel, GLint maxLevel,
const void *data)
{
int level, levels;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1 || height < 1) {
return GLU_INVALID_VALUE;
}
 
levels = computeLog(width);
level = computeLog(height);
if (level > levels) levels=level;
 
levels+= userLevel;
if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
return GLU_INVALID_VALUE;
 
return gluBuild2DMipmapLevelsCore(target, internalFormat,
width, height,
width, height,
format, type,
userLevel, baseLevel, maxLevel,
data);
} /* gluBuild2DMipmapLevels() */
 
GLint GLAPIENTRY
gluBuild2DMipmaps(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const void *data)
{
GLint widthPowerOf2, heightPowerOf2;
int level, levels;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1 || height < 1) {
return GLU_INVALID_VALUE;
}
 
closestFit(target,width,height,internalFormat,format,type,
&widthPowerOf2,&heightPowerOf2);
 
levels = computeLog(widthPowerOf2);
level = computeLog(heightPowerOf2);
if (level > levels) levels=level;
 
return gluBuild2DMipmapLevelsCore(target,internalFormat,
width, height,
widthPowerOf2,heightPowerOf2,
format,type,
0,0,levels,data);
} /* gluBuild2DMipmaps() */
 
#if 0
/*
** This routine is for the limited case in which
** type == GL_UNSIGNED_BYTE && format != index &&
** unpack_alignment = 1 && unpack_swap_bytes == false
**
** so all of the work data can be kept as ubytes instead of shorts.
*/
static int fastBuild2DMipmaps(const PixelStorageModes *psm,
GLenum target, GLint components, GLint width,
GLint height, GLenum format,
GLenum type, void *data)
{
GLint newwidth, newheight;
GLint level, levels;
GLubyte *newImage;
GLint newImage_width;
GLint newImage_height;
GLubyte *otherImage;
GLubyte *imageTemp;
GLint memreq;
GLint cmpts;
 
 
#if 0
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
newwidth = nearestPower(width);
if (newwidth > maxsize) newwidth = maxsize;
newheight = nearestPower(height);
if (newheight > maxsize) newheight = maxsize;
#else
closestFit(target,width,height,components,format,type,
&newwidth,&newheight);
#endif
levels = computeLog(newwidth);
level = computeLog(newheight);
if (level > levels) levels=level;
 
cmpts = elements_per_group(format,type);
 
otherImage = NULL;
/**
** No need to copy the user data if its in the packed correctly.
** Make sure that later routines don't change that data.
*/
if (psm->unpack_skip_rows == 0 && psm->unpack_skip_pixels == 0) {
newImage = (GLubyte *)data;
newImage_width = width;
newImage_height = height;
} else {
GLint rowsize;
GLint groups_per_line;
GLint elements_per_line;
const GLubyte *start;
const GLubyte *iter;
GLubyte *iter2;
GLint i, j;
 
newImage = (GLubyte *)
malloc(image_size(width, height, format, GL_UNSIGNED_BYTE));
newImage_width = width;
newImage_height = height;
if (newImage == NULL) {
return GLU_OUT_OF_MEMORY;
}
 
/*
** Abbreviated version of fill_image for this restricted case.
*/
if (psm->unpack_row_length > 0) {
groups_per_line = psm->unpack_row_length;
} else {
groups_per_line = width;
}
rowsize = groups_per_line * cmpts;
elements_per_line = width * cmpts;
start = (const GLubyte *) data + psm->unpack_skip_rows * rowsize +
psm->unpack_skip_pixels * cmpts;
iter2 = newImage;
 
for (i = 0; i < height; i++) {
iter = start;
for (j = 0; j < elements_per_line; j++) {
*iter2 = *iter;
iter++;
iter2++;
}
start += rowsize;
}
}
 
 
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
 
for (level = 0; level <= levels; level++) {
if (newImage_width == newwidth && newImage_height == newheight) {
/* Use newImage for this level */
glTexImage2D(target, level, components, newImage_width,
newImage_height, 0, format, GL_UNSIGNED_BYTE,
(void *) newImage);
} else {
if (otherImage == NULL) {
memreq =
image_size(newwidth, newheight, format, GL_UNSIGNED_BYTE);
otherImage = (GLubyte *) malloc(memreq);
if (otherImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH,psm->unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES,psm->unpack_swap_bytes);
return GLU_OUT_OF_MEMORY;
}
}
/*
scale_internal_ubyte(cmpts, newImage_width, newImage_height,
newImage, newwidth, newheight, otherImage);
*/
/* Swap newImage and otherImage */
imageTemp = otherImage;
otherImage = newImage;
newImage = imageTemp;
 
newImage_width = newwidth;
newImage_height = newheight;
glTexImage2D(target, level, components, newImage_width,
newImage_height, 0, format, GL_UNSIGNED_BYTE,
(void *) newImage);
}
if (newwidth > 1) newwidth /= 2;
if (newheight > 1) newheight /= 2;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, psm->unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm->unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm->unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm->unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm->unpack_swap_bytes);
 
if (newImage != (const GLubyte *)data) {
free((GLbyte *) newImage);
}
if (otherImage && otherImage != (const GLubyte *)data) {
free((GLbyte *) otherImage);
}
return 0;
}
#endif
 
/*
* Utility Routines
*/
static GLint elements_per_group(GLenum format, GLenum type)
{
/*
* Return the number of elements per group of a specified format
*/
 
/* If the type is packedpixels then answer is 1 (ignore format) */
if (type == GL_UNSIGNED_BYTE_3_3_2 ||
type == GL_UNSIGNED_BYTE_2_3_3_REV ||
type == GL_UNSIGNED_SHORT_5_6_5 ||
type == GL_UNSIGNED_SHORT_5_6_5_REV ||
type == GL_UNSIGNED_SHORT_4_4_4_4 ||
type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
type == GL_UNSIGNED_SHORT_5_5_5_1 ||
type == GL_UNSIGNED_SHORT_1_5_5_5_REV ||
type == GL_UNSIGNED_INT_8_8_8_8 ||
type == GL_UNSIGNED_INT_8_8_8_8_REV ||
type == GL_UNSIGNED_INT_10_10_10_2 ||
type == GL_UNSIGNED_INT_2_10_10_10_REV) {
return 1;
}
 
/* Types are not packed pixels, so get elements per group */
switch(format) {
case GL_RGB:
case GL_BGR:
return 3;
case GL_LUMINANCE_ALPHA:
return 2;
case GL_RGBA:
case GL_BGRA:
return 4;
default:
return 1;
}
}
 
static GLfloat bytes_per_element(GLenum type)
{
/*
* Return the number of bytes per element, based on the element type
*/
switch(type) {
case GL_BITMAP:
return 1.0 / 8.0;
case GL_UNSIGNED_SHORT:
return(sizeof(GLushort));
case GL_SHORT:
return(sizeof(GLshort));
case GL_UNSIGNED_BYTE:
return(sizeof(GLubyte));
case GL_BYTE:
return(sizeof(GLbyte));
case GL_INT:
return(sizeof(GLint));
case GL_UNSIGNED_INT:
return(sizeof(GLuint));
case GL_FLOAT:
return(sizeof(GLfloat));
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
return(sizeof(GLubyte));
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:
return(sizeof(GLushort));
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:
return(sizeof(GLuint));
default:
return 4;
}
}
 
static GLint is_index(GLenum format)
{
return format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX;
}
 
/*
** Compute memory required for internal packed array of data of given type
** and format.
*/
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
{
int bytes_per_row;
int components;
 
assert(width > 0);
assert(height > 0);
components = elements_per_group(format,type);
if (type == GL_BITMAP) {
bytes_per_row = (width + 7) / 8;
} else {
bytes_per_row = bytes_per_element(type) * width;
}
return bytes_per_row * height * components;
}
 
/*
** Extract array from user's data applying all pixel store modes.
** The internal format used is an array of unsigned shorts.
*/
static void fill_image(const PixelStorageModes *psm,
GLint width, GLint height, GLenum format,
GLenum type, GLboolean index_format,
const void *userdata, GLushort *newimage)
{
GLint components;
GLint element_size;
GLint rowsize;
GLint padding;
GLint groups_per_line;
GLint group_size;
GLint elements_per_line;
const GLubyte *start;
const GLubyte *iter;
GLushort *iter2;
GLint i, j, k;
GLint myswap_bytes;
 
myswap_bytes = psm->unpack_swap_bytes;
components = elements_per_group(format,type);
if (psm->unpack_row_length > 0) {
groups_per_line = psm->unpack_row_length;
} else {
groups_per_line = width;
}
 
/* All formats except GL_BITMAP fall out trivially */
if (type == GL_BITMAP) {
GLint bit_offset;
GLint current_bit;
 
rowsize = (groups_per_line * components + 7) / 8;
padding = (rowsize % psm->unpack_alignment);
if (padding) {
rowsize += psm->unpack_alignment - padding;
}
start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
(psm->unpack_skip_pixels * components / 8);
elements_per_line = width * components;
iter2 = newimage;
for (i = 0; i < height; i++) {
iter = start;
bit_offset = (psm->unpack_skip_pixels * components) % 8;
for (j = 0; j < elements_per_line; j++) {
/* Retrieve bit */
if (psm->unpack_lsb_first) {
current_bit = iter[0] & (1 << bit_offset);
} else {
current_bit = iter[0] & (1 << (7 - bit_offset));
}
if (current_bit) {
if (index_format) {
*iter2 = 1;
} else {
*iter2 = 65535;
}
} else {
*iter2 = 0;
}
bit_offset++;
if (bit_offset == 8) {
bit_offset = 0;
iter++;
}
iter2++;
}
start += rowsize;
}
} else {
element_size = bytes_per_element(type);
group_size = element_size * components;
if (element_size == 1) myswap_bytes = 0;
 
rowsize = groups_per_line * group_size;
padding = (rowsize % psm->unpack_alignment);
if (padding) {
rowsize += psm->unpack_alignment - padding;
}
start = (const GLubyte *) userdata + psm->unpack_skip_rows * rowsize +
psm->unpack_skip_pixels * group_size;
elements_per_line = width * components;
 
iter2 = newimage;
for (i = 0; i < height; i++) {
iter = start;
for (j = 0; j < elements_per_line; j++) {
Type_Widget widget;
float extractComponents[4];
 
switch(type) {
case GL_UNSIGNED_BYTE_3_3_2:
extract332(0,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
extract233rev(0,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_BYTE:
if (index_format) {
*iter2++ = *iter;
} else {
*iter2++ = (*iter) * 257;
}
break;
case GL_BYTE:
if (index_format) {
*iter2++ = *((const GLbyte *) iter);
} else {
/* rough approx */
*iter2++ = (*((const GLbyte *) iter)) * 516;
}
break;
case GL_UNSIGNED_SHORT_5_6_5:
extract565(myswap_bytes,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
extract565rev(myswap_bytes,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
extract4444(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
extract4444rev(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
extract5551(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
extract1555rev(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
if (myswap_bytes) {
widget.ub[0] = iter[1];
widget.ub[1] = iter[0];
} else {
widget.ub[0] = iter[0];
widget.ub[1] = iter[1];
}
if (type == GL_SHORT) {
if (index_format) {
*iter2++ = widget.s[0];
} else {
/* rough approx */
*iter2++ = widget.s[0]*2;
}
} else {
*iter2++ = widget.us[0];
}
break;
case GL_UNSIGNED_INT_8_8_8_8:
extract8888(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
extract8888rev(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_10_10_10_2:
extract1010102(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
extract2101010rev(myswap_bytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
if (myswap_bytes) {
widget.ub[0] = iter[3];
widget.ub[1] = iter[2];
widget.ub[2] = iter[1];
widget.ub[3] = iter[0];
} else {
widget.ub[0] = iter[0];
widget.ub[1] = iter[1];
widget.ub[2] = iter[2];
widget.ub[3] = iter[3];
}
if (type == GL_FLOAT) {
if (index_format) {
*iter2++ = widget.f;
} else {
*iter2++ = 65535 * widget.f;
}
} else if (type == GL_UNSIGNED_INT) {
if (index_format) {
*iter2++ = widget.ui;
} else {
*iter2++ = widget.ui >> 16;
}
} else {
if (index_format) {
*iter2++ = widget.i;
} else {
*iter2++ = widget.i >> 15;
}
}
break;
}
iter += element_size;
} /* for j */
start += rowsize;
#if 1
/* want 'iter' pointing at start, not within, row for assertion
* purposes
*/
iter= start;
#endif
} /* for i */
 
/* iterators should be one byte past end */
if (!isTypePackedPixel(type)) {
assert(iter2 == &newimage[width*height*components]);
}
else {
assert(iter2 == &newimage[width*height*
elements_per_group(format,0)]);
}
assert( iter == &((const GLubyte *)userdata)[rowsize*height +
psm->unpack_skip_rows * rowsize +
psm->unpack_skip_pixels * group_size] );
 
} /* else */
} /* fill_image() */
 
/*
** Insert array into user's data applying all pixel store modes.
** The internal format is an array of unsigned shorts.
** empty_image() because it is the opposite of fill_image().
*/
static void empty_image(const PixelStorageModes *psm,
GLint width, GLint height, GLenum format,
GLenum type, GLboolean index_format,
const GLushort *oldimage, void *userdata)
{
GLint components;
GLint element_size;
GLint rowsize;
GLint padding;
GLint groups_per_line;
GLint group_size;
GLint elements_per_line;
GLubyte *start;
GLubyte *iter;
const GLushort *iter2;
GLint i, j, k;
GLint myswap_bytes;
 
myswap_bytes = psm->pack_swap_bytes;
components = elements_per_group(format,type);
if (psm->pack_row_length > 0) {
groups_per_line = psm->pack_row_length;
} else {
groups_per_line = width;
}
 
/* All formats except GL_BITMAP fall out trivially */
if (type == GL_BITMAP) {
GLint bit_offset;
GLint current_bit;
 
rowsize = (groups_per_line * components + 7) / 8;
padding = (rowsize % psm->pack_alignment);
if (padding) {
rowsize += psm->pack_alignment - padding;
}
start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
(psm->pack_skip_pixels * components / 8);
elements_per_line = width * components;
iter2 = oldimage;
for (i = 0; i < height; i++) {
iter = start;
bit_offset = (psm->pack_skip_pixels * components) % 8;
for (j = 0; j < elements_per_line; j++) {
if (index_format) {
current_bit = iter2[0] & 1;
} else {
if (iter2[0] > 32767) {
current_bit = 1;
} else {
current_bit = 0;
}
}
 
if (current_bit) {
if (psm->pack_lsb_first) {
*iter |= (1 << bit_offset);
} else {
*iter |= (1 << (7 - bit_offset));
}
} else {
if (psm->pack_lsb_first) {
*iter &= ~(1 << bit_offset);
} else {
*iter &= ~(1 << (7 - bit_offset));
}
}
 
bit_offset++;
if (bit_offset == 8) {
bit_offset = 0;
iter++;
}
iter2++;
}
start += rowsize;
}
} else {
float shoveComponents[4];
 
element_size = bytes_per_element(type);
group_size = element_size * components;
if (element_size == 1) myswap_bytes = 0;
 
rowsize = groups_per_line * group_size;
padding = (rowsize % psm->pack_alignment);
if (padding) {
rowsize += psm->pack_alignment - padding;
}
start = (GLubyte *) userdata + psm->pack_skip_rows * rowsize +
psm->pack_skip_pixels * group_size;
elements_per_line = width * components;
 
iter2 = oldimage;
for (i = 0; i < height; i++) {
iter = start;
for (j = 0; j < elements_per_line; j++) {
Type_Widget widget;
 
switch(type) {
case GL_UNSIGNED_BYTE_3_3_2:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove332(shoveComponents,0,(void *)iter);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove233rev(shoveComponents,0,(void *)iter);
break;
case GL_UNSIGNED_BYTE:
if (index_format) {
*iter = *iter2++;
} else {
*iter = *iter2++ >> 8;
}
break;
case GL_BYTE:
if (index_format) {
*((GLbyte *) iter) = *iter2++;
} else {
*((GLbyte *) iter) = *iter2++ >> 9;
}
break;
case GL_UNSIGNED_SHORT_5_6_5:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove565(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
}
else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove565rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
}
else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove4444(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove5551(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
if (type == GL_SHORT) {
if (index_format) {
widget.s[0] = *iter2++;
} else {
widget.s[0] = *iter2++ >> 1;
}
} else {
widget.us[0] = *iter2++;
}
if (myswap_bytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
iter[0] = widget.ub[0];
iter[1] = widget.ub[1];
}
break;
case GL_UNSIGNED_INT_8_8_8_8:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove8888(shoveComponents,0,(void *)&widget.ui);
if (myswap_bytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
 
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove8888rev(shoveComponents,0,(void *)&widget.ui);
if (myswap_bytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_UNSIGNED_INT_10_10_10_2:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove1010102(shoveComponents,0,(void *)&widget.ui);
if (myswap_bytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove2101010rev(shoveComponents,0,(void *)&widget.ui);
if (myswap_bytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
if (type == GL_FLOAT) {
if (index_format) {
widget.f = *iter2++;
} else {
widget.f = *iter2++ / (float) 65535.0;
}
} else if (type == GL_UNSIGNED_INT) {
if (index_format) {
widget.ui = *iter2++;
} else {
widget.ui = (unsigned int) *iter2++ * 65537;
}
} else {
if (index_format) {
widget.i = *iter2++;
} else {
widget.i = ((unsigned int) *iter2++ * 65537)/2;
}
}
if (myswap_bytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
iter[0] = widget.ub[0];
iter[1] = widget.ub[1];
iter[2] = widget.ub[2];
iter[3] = widget.ub[3];
}
break;
}
iter += element_size;
} /* for j */
start += rowsize;
#if 1
/* want 'iter' pointing at start, not within, row for assertion
* purposes
*/
iter= start;
#endif
} /* for i */
 
/* iterators should be one byte past end */
if (!isTypePackedPixel(type)) {
assert(iter2 == &oldimage[width*height*components]);
}
else {
assert(iter2 == &oldimage[width*height*
elements_per_group(format,0)]);
}
assert( iter == &((GLubyte *)userdata)[rowsize*height +
psm->pack_skip_rows * rowsize +
psm->pack_skip_pixels * group_size] );
 
} /* else */
} /* empty_image() */
 
/*--------------------------------------------------------------------------
* Decimation of packed pixel types
*--------------------------------------------------------------------------
*/
static void extract332(int isSwap,
const void *packedPixel, GLfloat extractComponents[])
{
GLubyte ubyte= *(const GLubyte *)packedPixel;
 
isSwap= isSwap; /* turn off warnings */
 
/* 11100000 == 0xe0 */
/* 00011100 == 0x1c */
/* 00000011 == 0x03 */
 
extractComponents[0]= (float)((ubyte & 0xe0) >> 5) / 7.0;
extractComponents[1]= (float)((ubyte & 0x1c) >> 2) / 7.0; /* 7 = 2^3-1 */
extractComponents[2]= (float)((ubyte & 0x03) ) / 3.0; /* 3 = 2^2-1 */
} /* extract332() */
 
static void shove332(const GLfloat shoveComponents[],
int index, void *packedPixel)
{
/* 11100000 == 0xe0 */
/* 00011100 == 0x1c */
/* 00000011 == 0x03 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLubyte *)packedPixel)[index] =
((GLubyte)((shoveComponents[0] * 7)+0.5) << 5) & 0xe0;
((GLubyte *)packedPixel)[index] |=
((GLubyte)((shoveComponents[1] * 7)+0.5) << 2) & 0x1c;
((GLubyte *)packedPixel)[index] |=
((GLubyte)((shoveComponents[2] * 3)+0.5) ) & 0x03;
} /* shove332() */
 
static void extract233rev(int isSwap,
const void *packedPixel, GLfloat extractComponents[])
{
GLubyte ubyte= *(const GLubyte *)packedPixel;
 
isSwap= isSwap; /* turn off warnings */
 
/* 0000,0111 == 0x07 */
/* 0011,1000 == 0x38 */
/* 1100,0000 == 0xC0 */
 
extractComponents[0]= (float)((ubyte & 0x07) ) / 7.0;
extractComponents[1]= (float)((ubyte & 0x38) >> 3) / 7.0;
extractComponents[2]= (float)((ubyte & 0xC0) >> 6) / 3.0;
} /* extract233rev() */
 
static void shove233rev(const GLfloat shoveComponents[],
int index, void *packedPixel)
{
/* 0000,0111 == 0x07 */
/* 0011,1000 == 0x38 */
/* 1100,0000 == 0xC0 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLubyte *)packedPixel)[index] =
((GLubyte)((shoveComponents[0] * 7.0)+0.5) ) & 0x07;
((GLubyte *)packedPixel)[index]|=
((GLubyte)((shoveComponents[1] * 7.0)+0.5) << 3) & 0x38;
((GLubyte *)packedPixel)[index]|=
((GLubyte)((shoveComponents[2] * 3.0)+0.5) << 6) & 0xC0;
} /* shove233rev() */
 
static void extract565(int isSwap,
const void *packedPixel, GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 11111000,00000000 == 0xf800 */
/* 00000111,11100000 == 0x07e0 */
/* 00000000,00011111 == 0x001f */
 
extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
extractComponents[1]=(float)((ushort & 0x07e0) >> 5) / 63.0;/* 63 = 2^6-1*/
extractComponents[2]=(float)((ushort & 0x001f) ) / 31.0;
} /* extract565() */
 
static void shove565(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 11111000,00000000 == 0xf800 */
/* 00000111,11100000 == 0x07e0 */
/* 00000000,00011111 == 0x001f */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 63)+0.5) << 5) & 0x07e0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 31)+0.5) ) & 0x001f;
} /* shove565() */
 
static void extract565rev(int isSwap,
const void *packedPixel, GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 00000000,00011111 == 0x001f */
/* 00000111,11100000 == 0x07e0 */
/* 11111000,00000000 == 0xf800 */
 
extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
extractComponents[1]= (float)((ushort & 0x07E0) >> 5) / 63.0;
extractComponents[2]= (float)((ushort & 0xF800) >> 11) / 31.0;
} /* extract565rev() */
 
static void shove565rev(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 00000000,00011111 == 0x001f */
/* 00000111,11100000 == 0x07e0 */
/* 11111000,00000000 == 0xf800 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 31.0)+0.5) ) & 0x001F;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 63.0)+0.5) << 5) & 0x07E0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 31.0)+0.5) << 11) & 0xF800;
} /* shove565rev() */
 
static void extract4444(int isSwap,const void *packedPixel,
GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 11110000,00000000 == 0xf000 */
/* 00001111,00000000 == 0x0f00 */
/* 00000000,11110000 == 0x00f0 */
/* 00000000,00001111 == 0x000f */
 
extractComponents[0]= (float)((ushort & 0xf000) >> 12) / 15.0;/* 15=2^4-1 */
extractComponents[1]= (float)((ushort & 0x0f00) >> 8) / 15.0;
extractComponents[2]= (float)((ushort & 0x00f0) >> 4) / 15.0;
extractComponents[3]= (float)((ushort & 0x000f) ) / 15.0;
} /* extract4444() */
 
static void shove4444(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 15)+0.5) << 12) & 0xf000;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 15)+0.5) << 8) & 0x0f00;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 15)+0.5) << 4) & 0x00f0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[3] * 15)+0.5) ) & 0x000f;
} /* shove4444() */
 
static void extract4444rev(int isSwap,const void *packedPixel,
GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 00000000,00001111 == 0x000f */
/* 00000000,11110000 == 0x00f0 */
/* 00001111,00000000 == 0x0f00 */
/* 11110000,00000000 == 0xf000 */
 
/* 15 = 2^4-1 */
extractComponents[0]= (float)((ushort & 0x000F) ) / 15.0;
extractComponents[1]= (float)((ushort & 0x00F0) >> 4) / 15.0;
extractComponents[2]= (float)((ushort & 0x0F00) >> 8) / 15.0;
extractComponents[3]= (float)((ushort & 0xF000) >> 12) / 15.0;
} /* extract4444rev() */
 
static void shove4444rev(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 00000000,00001111 == 0x000f */
/* 00000000,11110000 == 0x00f0 */
/* 00001111,00000000 == 0x0f00 */
/* 11110000,00000000 == 0xf000 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 15)+0.5) ) & 0x000F;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 15)+0.5) << 4) & 0x00F0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 15)+0.5) << 8) & 0x0F00;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[3] * 15)+0.5) << 12) & 0xF000;
} /* shove4444rev() */
 
static void extract5551(int isSwap,const void *packedPixel,
GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 11111000,00000000 == 0xf800 */
/* 00000111,11000000 == 0x07c0 */
/* 00000000,00111110 == 0x003e */
/* 00000000,00000001 == 0x0001 */
 
extractComponents[0]=(float)((ushort & 0xf800) >> 11) / 31.0;/* 31 = 2^5-1*/
extractComponents[1]=(float)((ushort & 0x07c0) >> 6) / 31.0;
extractComponents[2]=(float)((ushort & 0x003e) >> 1) / 31.0;
extractComponents[3]=(float)((ushort & 0x0001) );
} /* extract5551() */
 
static void shove5551(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 11111000,00000000 == 0xf800 */
/* 00000111,11000000 == 0x07c0 */
/* 00000000,00111110 == 0x003e */
/* 00000000,00000001 == 0x0001 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 31)+0.5) << 11) & 0xf800;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 31)+0.5) << 6) & 0x07c0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 31)+0.5) << 1) & 0x003e;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[3])+0.5) ) & 0x0001;
} /* shove5551() */
 
static void extract1555rev(int isSwap,const void *packedPixel,
GLfloat extractComponents[])
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(packedPixel);
}
else {
ushort= *(const GLushort *)packedPixel;
}
 
/* 00000000,00011111 == 0x001F */
/* 00000011,11100000 == 0x03E0 */
/* 01111100,00000000 == 0x7C00 */
/* 10000000,00000000 == 0x8000 */
 
/* 31 = 2^5-1 */
extractComponents[0]= (float)((ushort & 0x001F) ) / 31.0;
extractComponents[1]= (float)((ushort & 0x03E0) >> 5) / 31.0;
extractComponents[2]= (float)((ushort & 0x7C00) >> 10) / 31.0;
extractComponents[3]= (float)((ushort & 0x8000) >> 15);
} /* extract1555rev() */
 
static void shove1555rev(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 00000000,00011111 == 0x001F */
/* 00000011,11100000 == 0x03E0 */
/* 01111100,00000000 == 0x7C00 */
/* 10000000,00000000 == 0x8000 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLushort *)packedPixel)[index] =
((GLushort)((shoveComponents[0] * 31)+0.5) ) & 0x001F;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[1] * 31)+0.5) << 5) & 0x03E0;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[2] * 31)+0.5) << 10) & 0x7C00;
((GLushort *)packedPixel)[index]|=
((GLushort)((shoveComponents[3])+0.5) << 15) & 0x8000;
} /* shove1555rev() */
 
static void extract8888(int isSwap,
const void *packedPixel, GLfloat extractComponents[])
{
GLuint uint;
 
if (isSwap) {
uint= __GLU_SWAP_4_BYTES(packedPixel);
}
else {
uint= *(const GLuint *)packedPixel;
}
 
/* 11111111,00000000,00000000,00000000 == 0xff000000 */
/* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
/* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
/* 00000000,00000000,00000000,11111111 == 0x000000ff */
 
/* 255 = 2^8-1 */
extractComponents[0]= (float)((uint & 0xff000000) >> 24) / 255.0;
extractComponents[1]= (float)((uint & 0x00ff0000) >> 16) / 255.0;
extractComponents[2]= (float)((uint & 0x0000ff00) >> 8) / 255.0;
extractComponents[3]= (float)((uint & 0x000000ff) ) / 255.0;
} /* extract8888() */
 
static void shove8888(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 11111111,00000000,00000000,00000000 == 0xff000000 */
/* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
/* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
/* 00000000,00000000,00000000,11111111 == 0x000000ff */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLuint *)packedPixel)[index] =
((GLuint)((shoveComponents[0] * 255)+0.5) << 24) & 0xff000000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[1] * 255)+0.5) << 16) & 0x00ff0000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[2] * 255)+0.5) << 8) & 0x0000ff00;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[3] * 255)+0.5) ) & 0x000000ff;
} /* shove8888() */
 
static void extract8888rev(int isSwap,
const void *packedPixel,GLfloat extractComponents[])
{
GLuint uint;
 
if (isSwap) {
uint= __GLU_SWAP_4_BYTES(packedPixel);
}
else {
uint= *(const GLuint *)packedPixel;
}
 
/* 00000000,00000000,00000000,11111111 == 0x000000ff */
/* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
/* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
/* 11111111,00000000,00000000,00000000 == 0xff000000 */
 
/* 255 = 2^8-1 */
extractComponents[0]= (float)((uint & 0x000000FF) ) / 255.0;
extractComponents[1]= (float)((uint & 0x0000FF00) >> 8) / 255.0;
extractComponents[2]= (float)((uint & 0x00FF0000) >> 16) / 255.0;
extractComponents[3]= (float)((uint & 0xFF000000) >> 24) / 255.0;
} /* extract8888rev() */
 
static void shove8888rev(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 00000000,00000000,00000000,11111111 == 0x000000ff */
/* 00000000,00000000,11111111,00000000 == 0x0000ff00 */
/* 00000000,11111111,00000000,00000000 == 0x00ff0000 */
/* 11111111,00000000,00000000,00000000 == 0xff000000 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLuint *)packedPixel)[index] =
((GLuint)((shoveComponents[0] * 255)+0.5) ) & 0x000000FF;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[1] * 255)+0.5) << 8) & 0x0000FF00;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[2] * 255)+0.5) << 16) & 0x00FF0000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[3] * 255)+0.5) << 24) & 0xFF000000;
} /* shove8888rev() */
 
static void extract1010102(int isSwap,
const void *packedPixel,GLfloat extractComponents[])
{
GLuint uint;
 
if (isSwap) {
uint= __GLU_SWAP_4_BYTES(packedPixel);
}
else {
uint= *(const GLuint *)packedPixel;
}
 
/* 11111111,11000000,00000000,00000000 == 0xffc00000 */
/* 00000000,00111111,11110000,00000000 == 0x003ff000 */
/* 00000000,00000000,00001111,11111100 == 0x00000ffc */
/* 00000000,00000000,00000000,00000011 == 0x00000003 */
 
/* 1023 = 2^10-1 */
extractComponents[0]= (float)((uint & 0xffc00000) >> 22) / 1023.0;
extractComponents[1]= (float)((uint & 0x003ff000) >> 12) / 1023.0;
extractComponents[2]= (float)((uint & 0x00000ffc) >> 2) / 1023.0;
extractComponents[3]= (float)((uint & 0x00000003) ) / 3.0;
} /* extract1010102() */
 
static void shove1010102(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 11111111,11000000,00000000,00000000 == 0xffc00000 */
/* 00000000,00111111,11110000,00000000 == 0x003ff000 */
/* 00000000,00000000,00001111,11111100 == 0x00000ffc */
/* 00000000,00000000,00000000,00000011 == 0x00000003 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLuint *)packedPixel)[index] =
((GLuint)((shoveComponents[0] * 1023)+0.5) << 22) & 0xffc00000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[1] * 1023)+0.5) << 12) & 0x003ff000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[2] * 1023)+0.5) << 2) & 0x00000ffc;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[3] * 3)+0.5) ) & 0x00000003;
} /* shove1010102() */
 
static void extract2101010rev(int isSwap,
const void *packedPixel,
GLfloat extractComponents[])
{
GLuint uint;
 
if (isSwap) {
uint= __GLU_SWAP_4_BYTES(packedPixel);
}
else {
uint= *(const GLuint *)packedPixel;
}
 
/* 00000000,00000000,00000011,11111111 == 0x000003FF */
/* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
/* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
/* 11000000,00000000,00000000,00000000 == 0xC0000000 */
 
/* 1023 = 2^10-1 */
extractComponents[0]= (float)((uint & 0x000003FF) ) / 1023.0;
extractComponents[1]= (float)((uint & 0x000FFC00) >> 10) / 1023.0;
extractComponents[2]= (float)((uint & 0x3FF00000) >> 20) / 1023.0;
extractComponents[3]= (float)((uint & 0xC0000000) >> 30) / 3.0;
/* 3 = 2^2-1 */
} /* extract2101010rev() */
 
static void shove2101010rev(const GLfloat shoveComponents[],
int index,void *packedPixel)
{
/* 00000000,00000000,00000011,11111111 == 0x000003FF */
/* 00000000,00001111,11111100,00000000 == 0x000FFC00 */
/* 00111111,11110000,00000000,00000000 == 0x3FF00000 */
/* 11000000,00000000,00000000,00000000 == 0xC0000000 */
 
assert(0.0 <= shoveComponents[0] && shoveComponents[0] <= 1.0);
assert(0.0 <= shoveComponents[1] && shoveComponents[1] <= 1.0);
assert(0.0 <= shoveComponents[2] && shoveComponents[2] <= 1.0);
assert(0.0 <= shoveComponents[3] && shoveComponents[3] <= 1.0);
 
/* due to limited precision, need to round before shoving */
((GLuint *)packedPixel)[index] =
((GLuint)((shoveComponents[0] * 1023)+0.5) ) & 0x000003FF;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[1] * 1023)+0.5) << 10) & 0x000FFC00;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[2] * 1023)+0.5) << 20) & 0x3FF00000;
((GLuint *)packedPixel)[index]|=
((GLuint)((shoveComponents[3] * 3)+0.5) << 30) & 0xC0000000;
} /* shove2101010rev() */
 
static void scaleInternalPackedPixel(int components,
void (*extractPackedPixel)
(int, const void *,GLfloat []),
void (*shovePackedPixel)
(const GLfloat [], int, void *),
GLint widthIn,GLint heightIn,
const void *dataIn,
GLint widthOut,GLint heightOut,
void *dataOut,
GLint pixelSizeInBytes,
GLint rowSizeInBytes,GLint isSwap)
{
float convx;
float convy;
float percent;
 
/* Max components in a format is 4, so... */
float totals[4];
float extractTotals[4], extractMoreTotals[4], shoveTotals[4];
 
float area;
int i,j,k,xindex;
 
const char *temp, *temp0;
int outindex;
 
int lowx_int, highx_int, lowy_int, highy_int;
float x_percent, y_percent;
float lowx_float, highx_float, lowy_float, highy_float;
float convy_float, convx_float;
int convy_int, convx_int;
int l, m;
const char *left, *right;
 
if (widthIn == widthOut*2 && heightIn == heightOut*2) {
halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
widthIn, heightIn, dataIn, dataOut,
pixelSizeInBytes,rowSizeInBytes,isSwap);
return;
}
convy = (float) heightIn/heightOut;
convx = (float) widthIn/widthOut;
convy_int = floor(convy);
convy_float = convy - convy_int;
convx_int = floor(convx);
convx_float = convx - convx_int;
 
area = convx * convy;
 
lowy_int = 0;
lowy_float = 0;
highy_int = convy_int;
highy_float = convy_float;
 
for (i = 0; i < heightOut; i++) {
lowx_int = 0;
lowx_float = 0;
highx_int = convx_int;
highx_float = convx_float;
 
for (j = 0; j < widthOut; j++) {
/*
** Ok, now apply box filter to box that goes from (lowx, lowy)
** to (highx, highy) on input data into this pixel on output
** data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
 
/* calculate the value for pixels in the 1st row */
xindex = lowx_int*pixelSizeInBytes;
if((highy_int>lowy_int) && (highx_int>lowx_int)) {
 
y_percent = 1-lowy_float;
temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
percent = y_percent * (1-lowx_float);
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
left = temp;
for(l = lowx_int+1; l < highx_int; l++) {
temp += pixelSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * y_percent;
}
#endif
}
temp += pixelSizeInBytes;
right = temp;
percent = y_percent * highx_float;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
 
/* calculate the value for pixels in the last row */
y_percent = highy_float;
percent = y_percent * (1-lowx_float);
temp = (const char *)dataIn + xindex + highy_int * rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
for(l = lowx_int+1; l < highx_int; l++) {
temp += pixelSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * y_percent;
}
#endif
 
}
temp += pixelSizeInBytes;
percent = y_percent * highx_float;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
 
/* calculate the value for pixels in the 1st and last column */
for(m = lowy_int+1; m < highy_int; m++) {
left += rowSizeInBytes;
right += rowSizeInBytes;
#if 0
for (k = 0; k < components;
k++, left += element_size, right += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(left) * (1-lowx_float) +
__GLU_SWAP_2_BYTES(right) * highx_float;
} else {
totals[k] += *(const GLushort*)left * (1-lowx_float)
+ *(const GLushort*)right * highx_float;
}
}
#else
(*extractPackedPixel)(isSwap,left,extractTotals);
(*extractPackedPixel)(isSwap,right,extractMoreTotals);
for (k = 0; k < components; k++) {
totals[k]+= (extractTotals[k]*(1-lowx_float) +
extractMoreTotals[k]*highx_float);
}
#endif
}
} else if (highy_int > lowy_int) {
x_percent = highx_float - lowx_float;
percent = (1-lowy_float)*x_percent;
temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
for(m = lowy_int+1; m < highy_int; m++) {
temp += rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * x_percent;
} else {
totals[k] += *(const GLushort*)temp_index * x_percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * x_percent;
}
#endif
}
percent = x_percent * highy_float;
temp += rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
} else if (highx_int > lowx_int) {
y_percent = highy_float - lowy_float;
percent = (1-lowx_float)*y_percent;
temp = (const char *)dataIn + xindex + lowy_int*rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
for (l = lowx_int+1; l < highx_int; l++) {
temp += pixelSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] +=
__GLU_SWAP_2_BYTES(temp_index) * y_percent;
} else {
totals[k] += *(const GLushort*)temp_index * y_percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * y_percent;
}
#endif
}
temp += pixelSizeInBytes;
percent = y_percent * highx_float;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
} else {
percent = (highy_float-lowy_float)*(highx_float-lowx_float);
temp = (const char *)dataIn + xindex + lowy_int * rowSizeInBytes;
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index) * percent;
} else {
totals[k] += *(const GLushort*)temp_index * percent;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k] * percent;
}
#endif
}
 
/* this is for the pixels in the body */
temp0 = (const char *)dataIn + xindex + pixelSizeInBytes + (lowy_int+1)*rowSizeInBytes;
for (m = lowy_int+1; m < highy_int; m++) {
temp = temp0;
for(l = lowx_int+1; l < highx_int; l++) {
#if 0
for (k = 0, temp_index = temp; k < components;
k++, temp_index += element_size) {
if (myswap_bytes) {
totals[k] += __GLU_SWAP_2_BYTES(temp_index);
} else {
totals[k] += *(const GLushort*)temp_index;
}
}
#else
(*extractPackedPixel)(isSwap,temp,extractTotals);
for (k = 0; k < components; k++) {
totals[k]+= extractTotals[k];
}
#endif
temp += pixelSizeInBytes;
}
temp0 += rowSizeInBytes;
}
 
outindex = (j + (i * widthOut)); /* * (components == 1) */
#if 0
for (k = 0; k < components; k++) {
dataout[outindex + k] = totals[k]/area;
/*printf("totals[%d] = %f\n", k, totals[k]);*/
}
#else
for (k = 0; k < components; k++) {
shoveTotals[k]= totals[k]/area;
}
(*shovePackedPixel)(shoveTotals,outindex,(void *)dataOut);
#endif
lowx_int = highx_int;
lowx_float = highx_float;
highx_int += convx_int;
highx_float += convx_float;
if(highx_float > 1) {
highx_float -= 1.0;
highx_int++;
}
}
lowy_int = highy_int;
lowy_float = highy_float;
highy_int += convy_int;
highy_float += convy_float;
if(highy_float > 1) {
highy_float -= 1.0;
highy_int++;
}
}
 
assert(outindex == (widthOut*heightOut - 1));
} /* scaleInternalPackedPixel() */
 
/* rowSizeInBytes is at least the width (in bytes) due to padding on
* inputs; not always equal. Output NEVER has row padding.
*/
static void halveImagePackedPixel(int components,
void (*extractPackedPixel)
(int, const void *,GLfloat []),
void (*shovePackedPixel)
(const GLfloat [],int, void *),
GLint width, GLint height,
const void *dataIn, void *dataOut,
GLint pixelSizeInBytes,
GLint rowSizeInBytes, GLint isSwap)
{
/* handle case where there is only 1 column/row */
if (width == 1 || height == 1) {
assert(!(width == 1 && height == 1)); /* can't be 1x1 */
halve1DimagePackedPixel(components,extractPackedPixel,shovePackedPixel,
width,height,dataIn,dataOut,pixelSizeInBytes,
rowSizeInBytes,isSwap);
return;
}
 
{
int ii, jj;
 
int halfWidth= width / 2;
int halfHeight= height / 2;
const char *src= (const char *) dataIn;
int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
int outIndex= 0;
 
for (ii= 0; ii< halfHeight; ii++) {
for (jj= 0; jj< halfWidth; jj++) {
#define BOX4 4
float totals[4]; /* 4 is maximum components */
float extractTotals[BOX4][4]; /* 4 is maximum components */
int cc;
 
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
&extractTotals[1][0]);
(*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
&extractTotals[2][0]);
(*extractPackedPixel)(isSwap,
(src+rowSizeInBytes+pixelSizeInBytes),
&extractTotals[3][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 4 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED];
* totals[RED]/= 4.0;
*/
for (kk = 0; kk < BOX4; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX4;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
/* skip over to next square of 4 */
src+= pixelSizeInBytes + pixelSizeInBytes;
}
/* skip past pad bytes, if any, to get to next row */
src+= padBytes;
 
/* src is at beginning of a row here, but it's the second row of
* the square block of 4 pixels that we just worked on so we
* need to go one more row.
* i.e.,
* OO...
* here -->OO...
* but want -->OO...
* OO...
* ...
*/
src+= rowSizeInBytes;
}
 
/* both pointers must reach one byte after the end */
assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
assert(outIndex == halfWidth * halfHeight);
}
} /* halveImagePackedPixel() */
 
static void halve1DimagePackedPixel(int components,
void (*extractPackedPixel)
(int, const void *,GLfloat []),
void (*shovePackedPixel)
(const GLfloat [],int, void *),
GLint width, GLint height,
const void *dataIn, void *dataOut,
GLint pixelSizeInBytes,
GLint rowSizeInBytes, GLint isSwap)
{
int halfWidth= width / 2;
int halfHeight= height / 2;
const char *src= (const char *) dataIn;
int jj;
 
assert(width == 1 || height == 1); /* must be 1D */
assert(width != height); /* can't be square */
 
if (height == 1) { /* 1 row */
int outIndex= 0;
 
assert(width != 1); /* widthxheight can't be 1x1 */
halfHeight= 1;
 
/* one horizontal row with possible pad bytes */
 
for (jj= 0; jj< halfWidth; jj++) {
#define BOX2 2
float totals[4]; /* 4 is maximum components */
float extractTotals[BOX2][4]; /* 4 is maximum components */
int cc;
 
/* average two at a time, instead of four */
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
&extractTotals[1][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 2 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
* totals[RED]/= 2.0;
*/
for (kk = 0; kk < BOX2; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX2;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
/* skip over to next group of 2 */
src+= pixelSizeInBytes + pixelSizeInBytes;
}
 
{
int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
src+= padBytes; /* for assertion only */
}
assert(src == &((const char *)dataIn)[rowSizeInBytes]);
assert(outIndex == halfWidth * halfHeight);
}
else if (width == 1) { /* 1 column */
int outIndex= 0;
 
assert(height != 1); /* widthxheight can't be 1x1 */
halfWidth= 1;
/* one vertical column with possible pad bytes per row */
/* average two at a time */
 
for (jj= 0; jj< halfHeight; jj++) {
#define BOX2 2
float totals[4]; /* 4 is maximum components */
float extractTotals[BOX2][4]; /* 4 is maximum components */
int cc;
 
/* average two at a time, instead of four */
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
&extractTotals[1][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 2 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
* totals[RED]/= 2.0;
*/
for (kk = 0; kk < BOX2; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX2;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
src+= rowSizeInBytes + rowSizeInBytes; /* go to row after next */
}
 
assert(src == &((const char *)dataIn)[rowSizeInBytes*height]);
assert(outIndex == halfWidth * halfHeight);
}
} /* halve1DimagePackedPixel() */
 
/*===========================================================================*/
 
#ifdef RESOLVE_3D_TEXTURE_SUPPORT
/*
* This section ensures that GLU 1.3 will load and run on
* a GL 1.1 implementation. It dynamically resolves the
* call to glTexImage3D() which might not be available.
* Or is it might be supported as an extension.
* Contributed by Gerk Huisma <gerk@five-d.demon.nl>.
*/
 
typedef void (GLAPIENTRY *TexImage3Dproc)( GLenum target, GLint level,
GLenum internalFormat,
GLsizei width, GLsizei height,
GLsizei depth, GLint border,
GLenum format, GLenum type,
const GLvoid *pixels );
 
static TexImage3Dproc pTexImage3D = 0;
 
#if !defined(_WIN32) && !defined(__WIN32__)
# include <dlfcn.h>
# include <sys/types.h>
#else
WINGDIAPI PROC WINAPI wglGetProcAddress(LPCSTR);
#endif
 
static void gluTexImage3D( GLenum target, GLint level,
GLenum internalFormat,
GLsizei width, GLsizei height,
GLsizei depth, GLint border,
GLenum format, GLenum type,
const GLvoid *pixels )
{
if (!pTexImage3D) {
#if defined(_WIN32) || defined(__WIN32__)
pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3D");
if (!pTexImage3D)
pTexImage3D = (TexImage3Dproc) wglGetProcAddress("glTexImage3DEXT");
#else
void *libHandle = dlopen("libgl.so", RTLD_LAZY);
pTexImage3D = TexImage3Dproc) dlsym(libHandle, "glTexImage3D" );
if (!pTexImage3D)
pTexImage3D = (TexImage3Dproc) dlsym(libHandle,"glTexImage3DEXT");
dlclose(libHandle);
#endif
}
 
/* Now call glTexImage3D */
if (pTexImage3D)
pTexImage3D(target, level, internalFormat, width, height,
depth, border, format, type, pixels);
}
 
#else
 
/* Only bind to a GL 1.2 implementation: */
#define gluTexImage3D glTexImage3D
 
#endif
 
static GLint imageSize3D(GLint width, GLint height, GLint depth,
GLenum format, GLenum type)
{
int components= elements_per_group(format,type);
int bytes_per_row= bytes_per_element(type) * width;
 
assert(width > 0 && height > 0 && depth > 0);
assert(type != GL_BITMAP);
 
return bytes_per_row * height * depth * components;
} /* imageSize3D() */
 
static void fillImage3D(const PixelStorageModes *psm,
GLint width, GLint height, GLint depth, GLenum format,
GLenum type, GLboolean indexFormat,
const void *userImage, GLushort *newImage)
{
int myswapBytes;
int components;
int groupsPerLine;
int elementSize;
int groupSize;
int rowSize;
int padding;
int elementsPerLine;
int rowsPerImage;
int imageSize;
const GLubyte *start, *rowStart, *iter;
GLushort *iter2;
int ww, hh, dd, k;
 
myswapBytes= psm->unpack_swap_bytes;
components= elements_per_group(format,type);
if (psm->unpack_row_length > 0) {
groupsPerLine= psm->unpack_row_length;
}
else {
groupsPerLine= width;
}
elementSize= bytes_per_element(type);
groupSize= elementSize * components;
if (elementSize == 1) myswapBytes= 0;
 
/* 3dstuff begin */
if (psm->unpack_image_height > 0) {
rowsPerImage= psm->unpack_image_height;
}
else {
rowsPerImage= height;
}
/* 3dstuff end */
 
rowSize= groupsPerLine * groupSize;
padding= rowSize % psm->unpack_alignment;
if (padding) {
rowSize+= psm->unpack_alignment - padding;
}
 
imageSize= rowsPerImage * rowSize; /* 3dstuff */
 
start= (const GLubyte *)userImage + psm->unpack_skip_rows * rowSize +
psm->unpack_skip_pixels * groupSize +
/*3dstuff*/
psm->unpack_skip_images * imageSize;
elementsPerLine = width * components;
 
iter2= newImage;
for (dd= 0; dd < depth; dd++) {
rowStart= start;
 
for (hh= 0; hh < height; hh++) {
iter= rowStart;
 
for (ww= 0; ww < elementsPerLine; ww++) {
Type_Widget widget;
float extractComponents[4];
 
switch(type) {
case GL_UNSIGNED_BYTE:
if (indexFormat) {
*iter2++ = *iter;
} else {
*iter2++ = (*iter) * 257;
}
break;
case GL_BYTE:
if (indexFormat) {
*iter2++ = *((const GLbyte *) iter);
} else {
/* rough approx */
*iter2++ = (*((const GLbyte *) iter)) * 516;
}
break;
case GL_UNSIGNED_BYTE_3_3_2:
extract332(0,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
extract233rev(0,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_5_6_5:
extract565(myswapBytes,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
extract565rev(myswapBytes,iter,extractComponents);
for (k = 0; k < 3; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
extract4444(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
extract4444rev(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
extract5551(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
extract1555rev(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
if (myswapBytes) {
widget.ub[0] = iter[1];
widget.ub[1] = iter[0];
} else {
widget.ub[0] = iter[0];
widget.ub[1] = iter[1];
}
if (type == GL_SHORT) {
if (indexFormat) {
*iter2++ = widget.s[0];
} else {
/* rough approx */
*iter2++ = widget.s[0]*2;
}
} else {
*iter2++ = widget.us[0];
}
break;
case GL_UNSIGNED_INT_8_8_8_8:
extract8888(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
extract8888rev(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_10_10_10_2:
extract1010102(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
extract2101010rev(myswapBytes,iter,extractComponents);
for (k = 0; k < 4; k++) {
*iter2++ = (GLushort)(extractComponents[k]*65535);
}
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
if (myswapBytes) {
widget.ub[0] = iter[3];
widget.ub[1] = iter[2];
widget.ub[2] = iter[1];
widget.ub[3] = iter[0];
} else {
widget.ub[0] = iter[0];
widget.ub[1] = iter[1];
widget.ub[2] = iter[2];
widget.ub[3] = iter[3];
}
if (type == GL_FLOAT) {
if (indexFormat) {
*iter2++ = widget.f;
} else {
*iter2++ = 65535 * widget.f;
}
} else if (type == GL_UNSIGNED_INT) {
if (indexFormat) {
*iter2++ = widget.ui;
} else {
*iter2++ = widget.ui >> 16;
}
} else {
if (indexFormat) {
*iter2++ = widget.i;
} else {
*iter2++ = widget.i >> 15;
}
}
break;
default:
assert(0);
}
 
iter+= elementSize;
} /* for ww */
rowStart+= rowSize;
 
iter= rowStart; /* for assertion purposes */
} /* for hh */
 
start+= imageSize;
} /* for dd */
 
/* iterators should be one byte past end */
if (!isTypePackedPixel(type)) {
assert(iter2 == &newImage[width*height*depth*components]);
}
else {
assert(iter2 == &newImage[width*height*depth*
elements_per_group(format,0)]);
}
assert( iter == &((const GLubyte *)userImage)[rowSize*height*depth +
psm->unpack_skip_rows * rowSize +
psm->unpack_skip_pixels * groupSize +
/*3dstuff*/
psm->unpack_skip_images * imageSize] );
} /* fillImage3D () */
 
static void scaleInternal3D(GLint components,
GLint widthIn, GLint heightIn, GLint depthIn,
const GLushort *dataIn,
GLint widthOut, GLint heightOut, GLint depthOut,
GLushort *dataOut)
{
float x, lowx, highx, convx, halfconvx;
float y, lowy, highy, convy, halfconvy;
float z, lowz, highz, convz, halfconvz;
float xpercent,ypercent,zpercent;
float percent;
/* Max components in a format is 4, so... */
float totals[4];
float volume;
int i,j,d,k,zint,yint,xint,xindex,yindex,zindex;
int temp;
 
convz = (float) depthIn/depthOut;
convy = (float) heightIn/heightOut;
convx = (float) widthIn/widthOut;
halfconvx = convx/2;
halfconvy = convy/2;
halfconvz = convz/2;
for (d = 0; d < depthOut; d++) {
z = convz * (d+0.5);
if (depthIn > depthOut) {
highz = z + halfconvz;
lowz = z - halfconvz;
} else {
highz = z + 0.5;
lowz = z - 0.5;
}
for (i = 0; i < heightOut; i++) {
y = convy * (i+0.5);
if (heightIn > heightOut) {
highy = y + halfconvy;
lowy = y - halfconvy;
} else {
highy = y + 0.5;
lowy = y - 0.5;
}
for (j = 0; j < widthOut; j++) {
x = convx * (j+0.5);
if (widthIn > widthOut) {
highx = x + halfconvx;
lowx = x - halfconvx;
} else {
highx = x + 0.5;
lowx = x - 0.5;
}
 
/*
** Ok, now apply box filter to box that goes from (lowx, lowy,
** lowz) to (highx, highy, highz) on input data into this pixel
** on output data.
*/
totals[0] = totals[1] = totals[2] = totals[3] = 0.0;
volume = 0.0;
 
z = lowz;
zint = floor(z);
while (z < highz) {
zindex = (zint + depthIn) % depthIn;
if (highz < zint+1) {
zpercent = highz - z;
} else {
zpercent = zint+1 - z;
}
 
y = lowy;
yint = floor(y);
while (y < highy) {
yindex = (yint + heightIn) % heightIn;
if (highy < yint+1) {
ypercent = highy - y;
} else {
ypercent = yint+1 - y;
}
 
x = lowx;
xint = floor(x);
 
while (x < highx) {
xindex = (xint + widthIn) % widthIn;
if (highx < xint+1) {
xpercent = highx - x;
} else {
xpercent = xint+1 - x;
}
 
percent = xpercent * ypercent * zpercent;
volume += percent;
 
temp = (xindex + (yindex*widthIn) +
(zindex*widthIn*heightIn)) * components;
for (k = 0; k < components; k++) {
assert(0 <= (temp+k) &&
(temp+k) <
(widthIn*heightIn*depthIn*components));
totals[k] += dataIn[temp + k] * percent;
}
 
xint++;
x = xint;
} /* while x */
 
yint++;
y = yint;
} /* while y */
 
zint++;
z = zint;
} /* while z */
 
temp = (j + (i * widthOut) +
(d*widthOut*heightOut)) * components;
for (k = 0; k < components; k++) {
/* totals[] should be rounded in the case of enlarging an
* RGB ramp when the type is 332 or 4444
*/
assert(0 <= (temp+k) &&
(temp+k) < (widthOut*heightOut*depthOut*components));
dataOut[temp + k] = (totals[k]+0.5)/volume;
}
} /* for j */
} /* for i */
} /* for d */
} /* scaleInternal3D() */
 
static void emptyImage3D(const PixelStorageModes *psm,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, GLboolean indexFormat,
const GLushort *oldImage, void *userImage)
{
int myswapBytes;
int components;
int groupsPerLine;
int elementSize;
int groupSize;
int rowSize;
int padding;
GLubyte *start, *rowStart, *iter;
int elementsPerLine;
const GLushort *iter2;
int ii, jj, dd, k;
int rowsPerImage;
int imageSize;
 
myswapBytes= psm->pack_swap_bytes;
components = elements_per_group(format,type);
if (psm->pack_row_length > 0) {
groupsPerLine = psm->pack_row_length;
}
else {
groupsPerLine = width;
}
 
elementSize= bytes_per_element(type);
groupSize= elementSize * components;
if (elementSize == 1) myswapBytes= 0;
 
/* 3dstuff begin */
if (psm->pack_image_height > 0) {
rowsPerImage= psm->pack_image_height;
}
else {
rowsPerImage= height;
}
 
/* 3dstuff end */
 
rowSize = groupsPerLine * groupSize;
padding = rowSize % psm->pack_alignment;
if (padding) {
rowSize+= psm->pack_alignment - padding;
}
 
imageSize= rowsPerImage * rowSize; /* 3dstuff */
 
start = (GLubyte *)userImage + psm->pack_skip_rows * rowSize +
psm->pack_skip_pixels * groupSize +
/*3dstuff*/
psm->pack_skip_images * imageSize;
elementsPerLine= width * components;
 
iter2 = oldImage;
for (dd= 0; dd < depth; dd++) {
rowStart= start;
 
for (ii= 0; ii< height; ii++) {
iter = rowStart;
 
for (jj = 0; jj < elementsPerLine; jj++) {
Type_Widget widget;
float shoveComponents[4];
 
switch(type){
case GL_UNSIGNED_BYTE:
if (indexFormat) {
*iter = *iter2++;
} else {
*iter = *iter2++ >> 8;
}
break;
case GL_BYTE:
if (indexFormat) {
*((GLbyte *) iter) = *iter2++;
} else {
*((GLbyte *) iter) = *iter2++ >> 9;
}
break;
case GL_UNSIGNED_BYTE_3_3_2:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove332(shoveComponents,0,(void *)iter);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove233rev(shoveComponents,0,(void *)iter);
break;
case GL_UNSIGNED_SHORT_5_6_5:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove565(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
}
else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
for (k = 0; k < 3; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove565rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
}
else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove4444(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove4444rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove5551(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove1555rev(shoveComponents,0,(void *)&widget.us[0]);
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
*(GLushort *)iter = widget.us[0];
}
break;
case GL_UNSIGNED_SHORT:
case GL_SHORT:
if (type == GL_SHORT) {
if (indexFormat) {
widget.s[0] = *iter2++;
} else {
widget.s[0] = *iter2++ >> 1;
}
} else {
widget.us[0] = *iter2++;
}
if (myswapBytes) {
iter[0] = widget.ub[1];
iter[1] = widget.ub[0];
} else {
iter[0] = widget.ub[0];
iter[1] = widget.ub[1];
}
break;
case GL_UNSIGNED_INT_8_8_8_8:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove8888(shoveComponents,0,(void *)&widget.ui);
if (myswapBytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove8888rev(shoveComponents,0,(void *)&widget.ui);
if (myswapBytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_UNSIGNED_INT_10_10_10_2:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove1010102(shoveComponents,0,(void *)&widget.ui);
if (myswapBytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
for (k = 0; k < 4; k++) {
shoveComponents[k]= *iter2++ / 65535.0;
}
shove2101010rev(shoveComponents,0,(void *)&widget.ui);
if (myswapBytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
*(GLuint *)iter= widget.ui;
}
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
if (type == GL_FLOAT) {
if (indexFormat) {
widget.f = *iter2++;
} else {
widget.f = *iter2++ / (float) 65535.0;
}
} else if (type == GL_UNSIGNED_INT) {
if (indexFormat) {
widget.ui = *iter2++;
} else {
widget.ui = (unsigned int) *iter2++ * 65537;
}
} else {
if (indexFormat) {
widget.i = *iter2++;
} else {
widget.i = ((unsigned int) *iter2++ * 65537)/2;
}
}
if (myswapBytes) {
iter[3] = widget.ub[0];
iter[2] = widget.ub[1];
iter[1] = widget.ub[2];
iter[0] = widget.ub[3];
} else {
iter[0] = widget.ub[0];
iter[1] = widget.ub[1];
iter[2] = widget.ub[2];
iter[3] = widget.ub[3];
}
break;
default:
assert(0);
}
 
iter+= elementSize;
} /* for jj */
 
rowStart+= rowSize;
} /* for ii */
 
start+= imageSize;
} /* for dd */
 
/* iterators should be one byte past end */
if (!isTypePackedPixel(type)) {
assert(iter2 == &oldImage[width*height*depth*components]);
}
else {
assert(iter2 == &oldImage[width*height*depth*
elements_per_group(format,0)]);
}
assert( iter == &((GLubyte *)userImage)[rowSize*height*depth +
psm->unpack_skip_rows * rowSize +
psm->unpack_skip_pixels * groupSize +
/*3dstuff*/
psm->unpack_skip_images * imageSize] );
} /* emptyImage3D() */
 
static
int gluScaleImage3D(GLenum format,
GLint widthIn, GLint heightIn, GLint depthIn,
GLenum typeIn, const void *dataIn,
GLint widthOut, GLint heightOut, GLint depthOut,
GLenum typeOut, void *dataOut)
{
int components;
GLushort *beforeImage, *afterImage;
PixelStorageModes psm;
 
if (widthIn == 0 || heightIn == 0 || depthIn == 0 ||
widthOut == 0 || heightOut == 0 || depthOut == 0) {
return 0;
}
 
if (widthIn < 0 || heightIn < 0 || depthIn < 0 ||
widthOut < 0 || heightOut < 0 || depthOut < 0) {
return GLU_INVALID_VALUE;
}
 
if (!legalFormat(format) || !legalType(typeIn) || !legalType(typeOut) ||
typeIn == GL_BITMAP || typeOut == GL_BITMAP) {
return GLU_INVALID_ENUM;
}
if (!isLegalFormatForPackedPixelType(format, typeIn)) {
return GLU_INVALID_OPERATION;
}
if (!isLegalFormatForPackedPixelType(format, typeOut)) {
return GLU_INVALID_OPERATION;
}
 
beforeImage = malloc(imageSize3D(widthIn, heightIn, depthIn, format,
GL_UNSIGNED_SHORT));
afterImage = malloc(imageSize3D(widthOut, heightOut, depthOut, format,
GL_UNSIGNED_SHORT));
if (beforeImage == NULL || afterImage == NULL) {
free(beforeImage);
free(afterImage);
return GLU_OUT_OF_MEMORY;
}
retrieveStoreModes3D(&psm);
 
fillImage3D(&psm,widthIn,heightIn,depthIn,format,typeIn, is_index(format),
dataIn, beforeImage);
components = elements_per_group(format,0);
scaleInternal3D(components,widthIn,heightIn,depthIn,beforeImage,
widthOut,heightOut,depthOut,afterImage);
emptyImage3D(&psm,widthOut,heightOut,depthOut,format,typeOut,
is_index(format),afterImage, dataOut);
free((void *) beforeImage);
free((void *) afterImage);
 
return 0;
} /* gluScaleImage3D() */
 
 
static void closestFit3D(GLenum target, GLint width, GLint height, GLint depth,
GLint internalFormat, GLenum format, GLenum type,
GLint *newWidth, GLint *newHeight, GLint *newDepth)
{
GLint widthPowerOf2= nearestPower(width);
GLint heightPowerOf2= nearestPower(height);
GLint depthPowerOf2= nearestPower(depth);
GLint proxyWidth;
 
do {
/* compute level 1 width & height & depth, clamping each at 1 */
GLint widthAtLevelOne= (widthPowerOf2 > 1) ?
widthPowerOf2 >> 1 :
widthPowerOf2;
GLint heightAtLevelOne= (heightPowerOf2 > 1) ?
heightPowerOf2 >> 1 :
heightPowerOf2;
GLint depthAtLevelOne= (depthPowerOf2 > 1) ?
depthPowerOf2 >> 1 :
depthPowerOf2;
GLenum proxyTarget = GL_PROXY_TEXTURE_3D;
assert(widthAtLevelOne > 0);
assert(heightAtLevelOne > 0);
assert(depthAtLevelOne > 0);
 
/* does width x height x depth at level 1 & all their mipmaps fit? */
assert(target == GL_TEXTURE_3D || target == GL_PROXY_TEXTURE_3D);
gluTexImage3D(proxyTarget, 1, /* must be non-zero */
internalFormat,
widthAtLevelOne,heightAtLevelOne,depthAtLevelOne,
0,format,type,NULL);
glGetTexLevelParameteriv(proxyTarget, 1,GL_TEXTURE_WIDTH,&proxyWidth);
/* does it fit??? */
if (proxyWidth == 0) { /* nope, so try again with these sizes */
if (widthPowerOf2 == 1 && heightPowerOf2 == 1 &&
depthPowerOf2 == 1) {
*newWidth= *newHeight= *newDepth= 1; /* must fit 1x1x1 texture */
return;
}
widthPowerOf2= widthAtLevelOne;
heightPowerOf2= heightAtLevelOne;
depthPowerOf2= depthAtLevelOne;
}
/* else it does fit */
} while (proxyWidth == 0);
/* loop must terminate! */
 
/* return the width & height at level 0 that fits */
*newWidth= widthPowerOf2;
*newHeight= heightPowerOf2;
*newDepth= depthPowerOf2;
/*printf("Proxy Textures\n");*/
} /* closestFit3D() */
 
static void halveImagePackedPixelSlice(int components,
void (*extractPackedPixel)
(int, const void *,GLfloat []),
void (*shovePackedPixel)
(const GLfloat [],int, void *),
GLint width, GLint height, GLint depth,
const void *dataIn, void *dataOut,
GLint pixelSizeInBytes,
GLint rowSizeInBytes,
GLint imageSizeInBytes,
GLint isSwap)
{
int ii, jj;
int halfWidth= width / 2;
int halfHeight= height / 2;
int halfDepth= depth / 2;
const char *src= (const char *)dataIn;
int outIndex= 0;
 
assert((width == 1 || height == 1) && depth >= 2);
 
if (width == height) { /* a 1-pixel column viewed from top */
assert(width == 1 && height == 1);
assert(depth >= 2);
 
for (ii= 0; ii< halfDepth; ii++) {
float totals[4];
float extractTotals[BOX2][4];
int cc;
 
(*extractPackedPixel)(isSwap,src,&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
&extractTotals[1][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* average 2 pixels since only a column */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
* totals[RED]/= 2.0;
*/
for (kk = 0; kk < BOX2; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX2;
} /* for cc */
(*shovePackedPixel)(totals,outIndex,dataOut);
outIndex++;
/* skip over to next group of 2 */
src+= imageSizeInBytes + imageSizeInBytes;
} /* for ii */
}
else if (height == 1) { /* horizontal slice viewed from top */
assert(width != 1);
 
for (ii= 0; ii< halfDepth; ii++) {
for (jj= 0; jj< halfWidth; jj++) {
float totals[4];
float extractTotals[BOX4][4];
int cc;
 
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
&extractTotals[1][0]);
(*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
&extractTotals[2][0]);
(*extractPackedPixel)(isSwap,
(src+imageSizeInBytes+pixelSizeInBytes),
&extractTotals[3][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 4 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED];
* totals[RED]/= 4.0;
*/
for (kk = 0; kk < BOX4; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX4;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
/* skip over to next horizontal square of 4 */
src+= imageSizeInBytes + imageSizeInBytes;
}
}
 
/* assert() */
}
else if (width == 1) { /* vertical slice viewed from top */
assert(height != 1);
 
for (ii= 0; ii< halfDepth; ii++) {
for (jj= 0; jj< halfHeight; jj++) {
float totals[4];
float extractTotals[BOX4][4];
int cc;
 
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
&extractTotals[1][0]);
(*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
&extractTotals[2][0]);
(*extractPackedPixel)(isSwap,
(src+imageSizeInBytes+rowSizeInBytes),
&extractTotals[3][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 4 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED];
* totals[RED]/= 4.0;
*/
for (kk = 0; kk < BOX4; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX4;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
 
/* skip over to next vertical square of 4 */
src+= imageSizeInBytes + imageSizeInBytes;
}
}
/* assert() */
}
 
} /* halveImagePackedPixelSlice() */
 
static void halveImagePackedPixel3D(int components,
void (*extractPackedPixel)
(int, const void *,GLfloat []),
void (*shovePackedPixel)
(const GLfloat [],int, void *),
GLint width, GLint height, GLint depth,
const void *dataIn, void *dataOut,
GLint pixelSizeInBytes,
GLint rowSizeInBytes,
GLint imageSizeInBytes,
GLint isSwap)
{
if (depth == 1) {
assert(1 <= width && 1 <= height);
 
halveImagePackedPixel(components,extractPackedPixel,shovePackedPixel,
width,height,dataIn,dataOut,pixelSizeInBytes,
rowSizeInBytes,isSwap);
return;
}
/* a horizontal or vertical slice viewed from top */
else if (width == 1 || height == 1) {
assert(1 <= depth);
 
halveImagePackedPixelSlice(components,
extractPackedPixel,shovePackedPixel,
width, height, depth, dataIn, dataOut,
pixelSizeInBytes, rowSizeInBytes,
imageSizeInBytes, isSwap);
return;
}
{
int ii, jj, dd;
 
int halfWidth= width / 2;
int halfHeight= height / 2;
int halfDepth= depth / 2;
const char *src= (const char *) dataIn;
int padBytes= rowSizeInBytes - (width*pixelSizeInBytes);
int outIndex= 0;
 
for (dd= 0; dd < halfDepth; dd++) {
for (ii= 0; ii< halfHeight; ii++) {
for (jj= 0; jj< halfWidth; jj++) {
#define BOX8 8
float totals[4]; /* 4 is maximum components */
float extractTotals[BOX8][4]; /* 4 is maximum components */
int cc;
 
(*extractPackedPixel)(isSwap,src,
&extractTotals[0][0]);
(*extractPackedPixel)(isSwap,(src+pixelSizeInBytes),
&extractTotals[1][0]);
(*extractPackedPixel)(isSwap,(src+rowSizeInBytes),
&extractTotals[2][0]);
(*extractPackedPixel)(isSwap,
(src+rowSizeInBytes+pixelSizeInBytes),
&extractTotals[3][0]);
 
(*extractPackedPixel)(isSwap,(src+imageSizeInBytes),
&extractTotals[4][0]);
(*extractPackedPixel)(isSwap,(src+pixelSizeInBytes+imageSizeInBytes),
&extractTotals[5][0]);
(*extractPackedPixel)(isSwap,(src+rowSizeInBytes+imageSizeInBytes),
&extractTotals[6][0]);
(*extractPackedPixel)(isSwap,
(src+rowSizeInBytes+pixelSizeInBytes+imageSizeInBytes),
&extractTotals[7][0]);
for (cc = 0; cc < components; cc++) {
int kk;
 
/* grab 8 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED]+
* extractTotals[4][RED]+extractTotals[5][RED]+
* extractTotals[6][RED]+extractTotals[7][RED];
* totals[RED]/= 8.0;
*/
for (kk = 0; kk < BOX8; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (float)BOX8;
}
(*shovePackedPixel)(totals,outIndex,dataOut);
 
outIndex++;
/* skip over to next square of 4 */
src+= pixelSizeInBytes + pixelSizeInBytes;
}
/* skip past pad bytes, if any, to get to next row */
src+= padBytes;
 
/* src is at beginning of a row here, but it's the second row of
* the square block of 4 pixels that we just worked on so we
* need to go one more row.
* i.e.,
* OO...
* here -->OO...
* but want -->OO...
* OO...
* ...
*/
src+= rowSizeInBytes;
}
 
src+= imageSizeInBytes;
} /* for dd */
 
/* both pointers must reach one byte after the end */
assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
assert(outIndex == halfWidth * halfHeight * halfDepth);
} /* for dd */
 
} /* halveImagePackedPixel3D() */
 
static int gluBuild3DMipmapLevelsCore(GLenum target, GLint internalFormat,
GLsizei width,
GLsizei height,
GLsizei depth,
GLsizei widthPowerOf2,
GLsizei heightPowerOf2,
GLsizei depthPowerOf2,
GLenum format, GLenum type,
GLint userLevel,
GLint baseLevel,GLint maxLevel,
const void *data)
{
GLint newWidth, newHeight, newDepth;
GLint level, levels;
const void *usersImage;
void *srcImage, *dstImage;
__GLU_INIT_SWAP_IMAGE;
GLint memReq;
GLint cmpts;
 
GLint myswapBytes, groupsPerLine, elementSize, groupSize;
GLint rowsPerImage, imageSize;
GLint rowSize, padding;
PixelStorageModes psm;
 
assert(checkMipmapArgs(internalFormat,format,type) == 0);
assert(width >= 1 && height >= 1 && depth >= 1);
assert(type != GL_BITMAP);
 
srcImage = dstImage = NULL;
 
newWidth= widthPowerOf2;
newHeight= heightPowerOf2;
newDepth= depthPowerOf2;
levels = computeLog(newWidth);
level = computeLog(newHeight);
if (level > levels) levels=level;
level = computeLog(newDepth);
if (level > levels) levels=level;
 
levels+= userLevel;
 
retrieveStoreModes3D(&psm);
myswapBytes = psm.unpack_swap_bytes;
cmpts = elements_per_group(format,type);
if (psm.unpack_row_length > 0) {
groupsPerLine = psm.unpack_row_length;
} else {
groupsPerLine = width;
}
 
elementSize = bytes_per_element(type);
groupSize = elementSize * cmpts;
if (elementSize == 1) myswapBytes = 0;
 
/* 3dstuff begin */
if (psm.unpack_image_height > 0) {
rowsPerImage= psm.unpack_image_height;
}
else {
rowsPerImage= height;
}
 
/* 3dstuff end */
rowSize = groupsPerLine * groupSize;
padding = (rowSize % psm.unpack_alignment);
if (padding) {
rowSize += psm.unpack_alignment - padding;
}
 
imageSize= rowsPerImage * rowSize; /* 3dstuff */
 
usersImage = (const GLubyte *)data + psm.unpack_skip_rows * rowSize +
psm.unpack_skip_pixels * groupSize +
/* 3dstuff */
psm.unpack_skip_images * imageSize;
 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
 
level = userLevel;
 
if (width == newWidth && height == newHeight && depth == newDepth) {
/* Use usersImage for level userLevel */
if (baseLevel <= level && level <= maxLevel) {
gluTexImage3D(target, level, internalFormat, width,
height, depth, 0, format, type,
usersImage);
}
if(levels == 0) { /* we're done. clean up and return */
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
return 0;
}
{
int nextWidth= newWidth/2;
int nextHeight= newHeight/2;
int nextDepth= newDepth/2;
 
/* clamp to 1 */
if (nextWidth < 1) nextWidth= 1;
if (nextHeight < 1) nextHeight= 1;
if (nextDepth < 1) nextDepth= 1;
memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
}
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memReq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memReq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memReq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memReq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memReq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memReq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memReq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memReq);
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:
dstImage = (GLushort *)malloc(memReq);
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:
dstImage = (GLuint *)malloc(memReq);
break;
default:
return GLU_INVALID_ENUM; /* assertion */
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
return GLU_OUT_OF_MEMORY;
}
else
switch(type) {
case GL_UNSIGNED_BYTE:
if (depth > 1) {
halveImage3D(cmpts,extractUbyte,shoveUbyte,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_ubyte(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize);
}
break;
case GL_BYTE:
if (depth > 1) {
halveImage3D(cmpts,extractSbyte,shoveSbyte,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_byte(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize);
}
break;
case GL_UNSIGNED_SHORT:
if (depth > 1) {
halveImage3D(cmpts,extractUshort,shoveUshort,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_ushort(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_SHORT:
if (depth > 1) {
halveImage3D(cmpts,extractSshort,shoveSshort,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_short(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_UNSIGNED_INT:
if (depth > 1) {
halveImage3D(cmpts,extractUint,shoveUint,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_uint(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_INT:
if (depth > 1) {
halveImage3D(cmpts,extractSint,shoveSint,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_int(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_FLOAT:
if (depth > 1 ) {
halveImage3D(cmpts,extractFloat,shoveFloat,
width,height,depth,
usersImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_float(cmpts,width,height,usersImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_UNSIGNED_BYTE_3_3_2:
assert(format == GL_RGB);
halveImagePackedPixel3D(3,extract332,shove332,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
assert(format == GL_RGB);
halveImagePackedPixel3D(3,extract233rev,shove233rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_6_5:
halveImagePackedPixel3D(3,extract565,shove565,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
halveImagePackedPixel3D(3,extract565rev,shove565rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
halveImagePackedPixel3D(4,extract4444,shove4444,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
halveImagePackedPixel3D(4,extract5551,shove5551,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_8_8_8_8:
halveImagePackedPixel3D(4,extract8888,shove8888,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_10_10_10_2:
halveImagePackedPixel3D(4,extract1010102,shove1010102,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
width,height,depth,usersImage,dstImage,
elementSize,rowSize,imageSize,myswapBytes);
break;
default:
assert(0);
break;
}
newWidth = width/2;
newHeight = height/2;
newDepth = depth/2;
/* clamp to 1 */
if (newWidth < 1) newWidth= 1;
if (newHeight < 1) newHeight= 1;
if (newDepth < 1) newDepth= 1;
 
myswapBytes = 0;
rowSize = newWidth * groupSize;
imageSize= rowSize * newHeight; /* 3dstuff */
memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
/* Swap srcImage and dstImage */
__GLU_SWAP_IMAGE(srcImage,dstImage);
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memReq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memReq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memReq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memReq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memReq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memReq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memReq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memReq);
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:
dstImage = (GLushort *)malloc(memReq);
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:
dstImage = (GLuint *)malloc(memReq);
break;
default:
return GLU_INVALID_ENUM; /* assertion */
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
free(srcImage);
return GLU_OUT_OF_MEMORY;
}
/* level userLevel+1 is in srcImage; level userLevel already saved */
level = userLevel+1;
} else {/* user's image is *not* nice power-of-2 sized square */
memReq = imageSize3D(newWidth, newHeight, newDepth, format, type);
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memReq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memReq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memReq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memReq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memReq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memReq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memReq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memReq);
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:
dstImage = (GLushort *)malloc(memReq);
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:
dstImage = (GLuint *)malloc(memReq);
break;
default:
return GLU_INVALID_ENUM; /* assertion */
}
 
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
return GLU_OUT_OF_MEMORY;
}
/*printf("Build3DMipmaps(): ScaleImage3D %d %d %d->%d %d %d\n",
width,height,depth,newWidth,newHeight,newDepth);*/
 
gluScaleImage3D(format, width, height, depth, type, usersImage,
newWidth, newHeight, newDepth, type, dstImage);
 
myswapBytes = 0;
rowSize = newWidth * groupSize;
imageSize = rowSize * newHeight; /* 3dstuff */
/* Swap dstImage and srcImage */
__GLU_SWAP_IMAGE(srcImage,dstImage);
 
if(levels != 0) { /* use as little memory as possible */
{
int nextWidth= newWidth/2;
int nextHeight= newHeight/2;
int nextDepth= newDepth/2;
if (nextWidth < 1) nextWidth= 1;
if (nextHeight < 1) nextHeight= 1;
if (nextDepth < 1) nextDepth= 1;
 
memReq = imageSize3D(nextWidth, nextHeight, nextDepth, format, type);
}
switch(type) {
case GL_UNSIGNED_BYTE:
dstImage = (GLubyte *)malloc(memReq);
break;
case GL_BYTE:
dstImage = (GLbyte *)malloc(memReq);
break;
case GL_UNSIGNED_SHORT:
dstImage = (GLushort *)malloc(memReq);
break;
case GL_SHORT:
dstImage = (GLshort *)malloc(memReq);
break;
case GL_UNSIGNED_INT:
dstImage = (GLuint *)malloc(memReq);
break;
case GL_INT:
dstImage = (GLint *)malloc(memReq);
break;
case GL_FLOAT:
dstImage = (GLfloat *)malloc(memReq);
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
dstImage = (GLubyte *)malloc(memReq);
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:
dstImage = (GLushort *)malloc(memReq);
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:
dstImage = (GLuint *)malloc(memReq);
break;
default:
return GLU_INVALID_ENUM; /* assertion */
}
if (dstImage == NULL) {
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
free(srcImage);
return GLU_OUT_OF_MEMORY;
}
}
/* level userLevel is in srcImage; nothing saved yet */
level = userLevel;
}
 
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
if (baseLevel <= level && level <= maxLevel) {
gluTexImage3D(target, level, internalFormat, newWidth, newHeight, newDepth,
0,format, type, (void *)srcImage);
}
level++; /* update current level for the loop */
for (; level <= levels; level++) {
switch(type) {
case GL_UNSIGNED_BYTE:
if (newDepth > 1) {
halveImage3D(cmpts,extractUbyte,shoveUbyte,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_ubyte(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize);
}
break;
case GL_BYTE:
if (newDepth > 1) {
halveImage3D(cmpts,extractSbyte,shoveSbyte,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_byte(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize);
}
break;
case GL_UNSIGNED_SHORT:
if (newDepth > 1) {
halveImage3D(cmpts,extractUshort,shoveUshort,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_ushort(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_SHORT:
if (newDepth > 1) {
halveImage3D(cmpts,extractSshort,shoveSshort,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_short(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_UNSIGNED_INT:
if (newDepth > 1) {
halveImage3D(cmpts,extractUint,shoveUint,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_uint(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_INT:
if (newDepth > 1) {
halveImage3D(cmpts,extractSint,shoveSint,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_int(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_FLOAT:
if (newDepth > 1) {
halveImage3D(cmpts,extractFloat,shoveFloat,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,groupSize,rowSize,
imageSize,myswapBytes);
}
else {
halveImage_float(cmpts,newWidth,newHeight,srcImage,dstImage,
elementSize,rowSize,groupSize,myswapBytes);
}
break;
case GL_UNSIGNED_BYTE_3_3_2:
halveImagePackedPixel3D(3,extract332,shove332,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_BYTE_2_3_3_REV:
halveImagePackedPixel3D(3,extract233rev,shove233rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_6_5:
halveImagePackedPixel3D(3,extract565,shove565,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_6_5_REV:
halveImagePackedPixel3D(3,extract565rev,shove565rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
halveImagePackedPixel3D(4,extract4444,shove4444,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
halveImagePackedPixel3D(4,extract4444rev,shove4444rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_5_5_5_1:
halveImagePackedPixel3D(4,extract5551,shove5551,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
halveImagePackedPixel3D(4,extract1555rev,shove1555rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_8_8_8_8:
halveImagePackedPixel3D(4,extract8888,shove8888,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_8_8_8_8_REV:
halveImagePackedPixel3D(4,extract8888rev,shove8888rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_10_10_10_2:
halveImagePackedPixel3D(4,extract1010102,shove1010102,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
case GL_UNSIGNED_INT_2_10_10_10_REV:
halveImagePackedPixel3D(4,extract2101010rev,shove2101010rev,
newWidth,newHeight,newDepth,
srcImage,dstImage,elementSize,rowSize,
imageSize,myswapBytes);
break;
default:
assert(0);
break;
}
 
__GLU_SWAP_IMAGE(srcImage,dstImage);
 
if (newWidth > 1) { newWidth /= 2; rowSize /= 2;}
if (newHeight > 1) { newHeight /= 2; imageSize = rowSize * newHeight; }
if (newDepth > 1) newDepth /= 2;
{
/* call tex image with srcImage untouched since it's not padded */
if (baseLevel <= level && level <= maxLevel) {
gluTexImage3D(target, level, internalFormat, newWidth, newHeight,
newDepth,0, format, type, (void *) srcImage);
}
}
} /* for level */
glPixelStorei(GL_UNPACK_ALIGNMENT, psm.unpack_alignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, psm.unpack_skip_rows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, psm.unpack_skip_pixels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, psm.unpack_row_length);
glPixelStorei(GL_UNPACK_SWAP_BYTES, psm.unpack_swap_bytes);
glPixelStorei(GL_UNPACK_SKIP_IMAGES, psm.unpack_skip_images);
glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, psm.unpack_image_height);
 
free(srcImage); /*if you get to here, a srcImage has always been malloc'ed*/
if (dstImage) { /* if it's non-rectangular and only 1 level */
free(dstImage);
}
return 0;
} /* gluBuild3DMipmapLevelsCore() */
 
GLint GLAPIENTRY
gluBuild3DMipmapLevels(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type,
GLint userLevel, GLint baseLevel, GLint maxLevel,
const void *data)
{
int level, levels;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1 || height < 1 || depth < 1) {
return GLU_INVALID_VALUE;
}
 
if(type == GL_BITMAP) {
return GLU_INVALID_ENUM;
}
 
levels = computeLog(width);
level = computeLog(height);
if (level > levels) levels=level;
level = computeLog(depth);
if (level > levels) levels=level;
 
levels+= userLevel;
if (!isLegalLevels(userLevel,baseLevel,maxLevel,levels))
return GLU_INVALID_VALUE;
 
return gluBuild3DMipmapLevelsCore(target, internalFormat,
width, height, depth,
width, height, depth,
format, type,
userLevel, baseLevel, maxLevel,
data);
} /* gluBuild3DMipmapLevels() */
 
GLint GLAPIENTRY
gluBuild3DMipmaps(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const void *data)
{
GLint widthPowerOf2, heightPowerOf2, depthPowerOf2;
int level, levels;
 
int rc= checkMipmapArgs(internalFormat,format,type);
if (rc != 0) return rc;
 
if (width < 1 || height < 1 || depth < 1) {
return GLU_INVALID_VALUE;
}
 
if(type == GL_BITMAP) {
return GLU_INVALID_ENUM;
}
 
closestFit3D(target,width,height,depth,internalFormat,format,type,
&widthPowerOf2,&heightPowerOf2,&depthPowerOf2);
 
levels = computeLog(widthPowerOf2);
level = computeLog(heightPowerOf2);
if (level > levels) levels=level;
level = computeLog(depthPowerOf2);
if (level > levels) levels=level;
 
return gluBuild3DMipmapLevelsCore(target, internalFormat,
width, height, depth,
widthPowerOf2, heightPowerOf2,
depthPowerOf2,
format, type, 0, 0, levels,
data);
} /* gluBuild3DMipmaps() */
 
static GLdouble extractUbyte(int isSwap, const void *ubyte)
{
isSwap= isSwap; /* turn off warnings */
 
assert(*((const GLubyte *)ubyte) <= 255);
 
return (GLdouble)(*((const GLubyte *)ubyte));
} /* extractUbyte() */
 
static void shoveUbyte(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value < 256.0);
 
((GLubyte *)data)[index]= (GLubyte)value;
} /* shoveUbyte() */
 
static GLdouble extractSbyte(int isSwap, const void *sbyte)
{
isSwap= isSwap; /* turn off warnings */
 
assert(*((const GLbyte *)sbyte) <= 127);
 
return (GLdouble)(*((const GLbyte *)sbyte));
} /* extractSbyte() */
 
static void shoveSbyte(GLdouble value, int index, void *data)
{
((GLbyte *)data)[index]= (GLbyte)value;
} /* shoveSbyte() */
 
static GLdouble extractUshort(int isSwap, const void *uitem)
{
GLushort ushort;
 
if (isSwap) {
ushort= __GLU_SWAP_2_BYTES(uitem);
}
else {
ushort= *(const GLushort *)uitem;
}
 
assert(ushort <= 65535);
 
return (GLdouble)ushort;
} /* extractUshort() */
 
static void shoveUshort(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value < 65536.0);
 
((GLushort *)data)[index]= (GLushort)value;
} /* shoveUshort() */
 
static GLdouble extractSshort(int isSwap, const void *sitem)
{
GLshort sshort;
 
if (isSwap) {
sshort= __GLU_SWAP_2_BYTES(sitem);
}
else {
sshort= *(const GLshort *)sitem;
}
 
assert(sshort <= 32767);
 
return (GLdouble)sshort;
} /* extractSshort() */
 
static void shoveSshort(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value < 32768.0);
 
((GLshort *)data)[index]= (GLshort)value;
} /* shoveSshort() */
 
static GLdouble extractUint(int isSwap, const void *uitem)
{
GLuint uint;
 
if (isSwap) {
uint= __GLU_SWAP_4_BYTES(uitem);
}
else {
uint= *(const GLuint *)uitem;
}
 
assert(uint <= 0xffffffff);
 
return (GLdouble)uint;
} /* extractUint() */
 
static void shoveUint(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value <= (GLdouble) UINT_MAX);
 
((GLuint *)data)[index]= (GLuint)value;
} /* shoveUint() */
 
static GLdouble extractSint(int isSwap, const void *sitem)
{
GLint sint;
 
if (isSwap) {
sint= __GLU_SWAP_4_BYTES(sitem);
}
else {
sint= *(const GLint *)sitem;
}
 
assert(sint <= 0x7fffffff);
 
return (GLdouble)sint;
} /* extractSint() */
 
static void shoveSint(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value <= (GLdouble) INT_MAX);
 
((GLint *)data)[index]= (GLint)value;
} /* shoveSint() */
 
static GLdouble extractFloat(int isSwap, const void *item)
{
GLfloat ffloat;
 
if (isSwap) {
ffloat= __GLU_SWAP_4_BYTES(item);
}
else {
ffloat= *(const GLfloat *)item;
}
 
assert(ffloat <= 1.0);
 
return (GLdouble)ffloat;
} /* extractFloat() */
 
static void shoveFloat(GLdouble value, int index, void *data)
{
assert(0.0 <= value && value <= 1.0);
 
((GLfloat *)data)[index]= value;
} /* shoveFloat() */
 
static void halveImageSlice(int components,
GLdouble (*extract)(int, const void *),
void (*shove)(GLdouble, int, void *),
GLint width, GLint height, GLint depth,
const void *dataIn, void *dataOut,
GLint elementSizeInBytes,
GLint groupSizeInBytes,
GLint rowSizeInBytes,
GLint imageSizeInBytes,
GLint isSwap)
{
int ii, jj;
int halfWidth= width / 2;
int halfHeight= height / 2;
int halfDepth= depth / 2;
const char *src= (const char *)dataIn;
int rowPadBytes= rowSizeInBytes - (width * groupSizeInBytes);
int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
int outIndex= 0;
 
assert((width == 1 || height == 1) && depth >= 2);
 
if (width == height) { /* a 1-pixel column viewed from top */
/* printf("1-column\n");*/
assert(width == 1 && height == 1);
assert(depth >= 2);
 
for (ii= 0; ii< halfDepth; ii++) {
int cc;
 
for (cc = 0; cc < components; cc++) {
double totals[4];
double extractTotals[BOX2][4];
int kk;
 
extractTotals[0][cc]= (*extract)(isSwap,src);
extractTotals[1][cc]= (*extract)(isSwap,(src+imageSizeInBytes));
 
/* average 2 pixels since only a column */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED];
* totals[RED]/= 2.0;
*/
for (kk = 0; kk < BOX2; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (double)BOX2;
 
(*shove)(totals[cc],outIndex,dataOut);
outIndex++;
src+= elementSizeInBytes;
} /* for cc */
 
/* skip over to next group of 2 */
src+= rowSizeInBytes;
} /* for ii */
 
assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
assert(outIndex == halfDepth * components);
}
else if (height == 1) { /* horizontal slice viewed from top */
/* printf("horizontal slice\n"); */
assert(width != 1);
 
for (ii= 0; ii< halfDepth; ii++) {
for (jj= 0; jj< halfWidth; jj++) {
int cc;
 
for (cc = 0; cc < components; cc++) {
int kk;
double totals[4];
double extractTotals[BOX4][4];
 
extractTotals[0][cc]=(*extract)(isSwap,src);
extractTotals[1][cc]=(*extract)(isSwap,
(src+groupSizeInBytes));
extractTotals[2][cc]=(*extract)(isSwap,
(src+imageSizeInBytes));
extractTotals[3][cc]=(*extract)(isSwap,
(src+imageSizeInBytes+groupSizeInBytes));
 
/* grab 4 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED];
* totals[RED]/= 4.0;
*/
for (kk = 0; kk < BOX4; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (double)BOX4;
 
(*shove)(totals[cc],outIndex,dataOut);
outIndex++;
 
src+= elementSizeInBytes;
} /* for cc */
 
/* skip over to next horizontal square of 4 */
src+= groupSizeInBytes;
} /* for jj */
src+= rowPadBytes;
 
src+= rowSizeInBytes;
} /* for ii */
 
assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
assert(outIndex == halfWidth * halfDepth * components);
}
else if (width == 1) { /* vertical slice viewed from top */
/* printf("vertical slice\n"); */
assert(height != 1);
 
for (ii= 0; ii< halfDepth; ii++) {
for (jj= 0; jj< halfHeight; jj++) {
int cc;
 
for (cc = 0; cc < components; cc++) {
int kk;
double totals[4];
double extractTotals[BOX4][4];
 
extractTotals[0][cc]=(*extract)(isSwap,src);
extractTotals[1][cc]=(*extract)(isSwap,
(src+rowSizeInBytes));
extractTotals[2][cc]=(*extract)(isSwap,
(src+imageSizeInBytes));
extractTotals[3][cc]=(*extract)(isSwap,
(src+imageSizeInBytes+rowSizeInBytes));
 
/* grab 4 pixels to average */
totals[cc]= 0.0;
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED];
* totals[RED]/= 4.0;
*/
for (kk = 0; kk < BOX4; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (double)BOX4;
 
(*shove)(totals[cc],outIndex,dataOut);
outIndex++;
 
src+= elementSizeInBytes;
} /* for cc */
src+= rowPadBytes;
 
/* skip over to next vertical square of 4 */
src+= rowSizeInBytes;
} /* for jj */
src+= imagePadBytes;
 
src+= imageSizeInBytes;
} /* for ii */
 
assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
assert(outIndex == halfHeight * halfDepth * components);
}
 
} /* halveImageSlice() */
 
static void halveImage3D(int components,
GLdouble (*extract)(int, const void *),
void (*shove)(GLdouble, int, void *),
GLint width, GLint height, GLint depth,
const void *dataIn, void *dataOut,
GLint elementSizeInBytes,
GLint groupSizeInBytes,
GLint rowSizeInBytes,
GLint imageSizeInBytes,
GLint isSwap)
{
assert(depth > 1);
 
/* a horizontal/vertical/one-column slice viewed from top */
if (width == 1 || height == 1) {
assert(1 <= depth);
 
halveImageSlice(components,extract,shove, width, height, depth,
dataIn, dataOut, elementSizeInBytes, groupSizeInBytes,
rowSizeInBytes, imageSizeInBytes, isSwap);
return;
}
{
int ii, jj, dd;
 
int halfWidth= width / 2;
int halfHeight= height / 2;
int halfDepth= depth / 2;
const char *src= (const char *) dataIn;
int rowPadBytes= rowSizeInBytes - (width*groupSizeInBytes);
int imagePadBytes= imageSizeInBytes - (width*height*groupSizeInBytes);
int outIndex= 0;
 
for (dd= 0; dd < halfDepth; dd++) {
for (ii= 0; ii< halfHeight; ii++) {
for (jj= 0; jj< halfWidth; jj++) {
int cc;
 
for (cc= 0; cc < components; cc++) {
int kk;
#define BOX8 8
double totals[4]; /* 4 is maximum components */
double extractTotals[BOX8][4]; /* 4 is maximum components */
 
extractTotals[0][cc]= (*extract)(isSwap,src);
extractTotals[1][cc]= (*extract)(isSwap,
(src+groupSizeInBytes));
extractTotals[2][cc]= (*extract)(isSwap,
(src+rowSizeInBytes));
extractTotals[3][cc]= (*extract)(isSwap,
(src+rowSizeInBytes+groupSizeInBytes));
 
extractTotals[4][cc]= (*extract)(isSwap,
(src+imageSizeInBytes));
 
extractTotals[5][cc]= (*extract)(isSwap,
(src+groupSizeInBytes+imageSizeInBytes));
extractTotals[6][cc]= (*extract)(isSwap,
(src+rowSizeInBytes+imageSizeInBytes));
extractTotals[7][cc]= (*extract)(isSwap,
(src+rowSizeInBytes+groupSizeInBytes+imageSizeInBytes));
 
totals[cc]= 0.0;
 
/* totals[RED]= extractTotals[0][RED]+extractTotals[1][RED]+
* extractTotals[2][RED]+extractTotals[3][RED]+
* extractTotals[4][RED]+extractTotals[5][RED]+
* extractTotals[6][RED]+extractTotals[7][RED];
* totals[RED]/= 8.0;
*/
for (kk = 0; kk < BOX8; kk++) {
totals[cc]+= extractTotals[kk][cc];
}
totals[cc]/= (double)BOX8;
 
(*shove)(totals[cc],outIndex,dataOut);
 
outIndex++;
 
src+= elementSizeInBytes; /* go to next component */
} /* for cc */
 
/* skip over to next square of 4 */
src+= groupSizeInBytes;
} /* for jj */
/* skip past pad bytes, if any, to get to next row */
src+= rowPadBytes;
 
/* src is at beginning of a row here, but it's the second row of
* the square block of 4 pixels that we just worked on so we
* need to go one more row.
* i.e.,
* OO...
* here -->OO...
* but want -->OO...
* OO...
* ...
*/
src+= rowSizeInBytes;
} /* for ii */
 
/* skip past pad bytes, if any, to get to next image */
src+= imagePadBytes;
 
src+= imageSizeInBytes;
} /* for dd */
 
/* both pointers must reach one byte after the end */
assert(src == &((const char *)dataIn)[rowSizeInBytes*height*depth]);
assert(outIndex == halfWidth * halfHeight * halfDepth * components);
}
} /* halveImage3D() */
 
 
 
/*** mipmap.c ***/
 
/contrib/sdk/samples/Mesa/osdemo.c
0,0 → 1,180
/*
* Demo of off-screen Mesa rendering
*
* See Mesa/include/GL/osmesa.h for documentation of the OSMesa functions.
*
* If you want to render BIG images you'll probably have to increase
* MAX_WIDTH and MAX_Height in src/config.h.
*
* This program is in the public domain.
*
* Brian Paul
*
* PPM output provided by Joerg Schmalzl.
* ASCII PPM output added by Brian Paul.
*
* Usage: osdemo [filename]
*/
 
 
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define GL_GLEXT_PROTOTYPES
#include "GL/osmesa.h"
#include <GL/glext.h>
#include "GL/glu.h"
#include "shaderutil.h"
#include <kos32sys.h>
 
int _CRT_MT=0;
 
static int Width = 500;
static int Height = 400;
 
int check_events();
 
GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
GLfloat angle = 0.0;
 
GLboolean animate = GL_TRUE; /* Animation */
GLfloat eyesep = 5.0; /* Eye separation. */
GLfloat fix_point = 40.0; /* Fixation point distance. */
GLfloat left, right, asp; /* Stereo frustum params. */
 
void Init( void );
void Reshape( int width, int height );
void Draw( void );
void Idle();
void Key(unsigned char key, int x, int y);
 
 
inline void Blit(void *bitmap, int dst_x, int dst_y,
int src_x, int src_y, int w, int h,
int src_w, int src_h, int stride)
{
volatile struct blit_call bc;
 
bc.dstx = dst_x;
bc.dsty = dst_y;
bc.w = w;
bc.h = h;
bc.srcx = src_x;
bc.srcy = src_y;
bc.srcw = src_w;
bc.srch = src_h;
bc.stride = stride;
bc.bitmap = bitmap;
 
__asm__ __volatile__(
"int $0x40"
::"a"(73),"b"(0),"c"(&bc.dstx));
 
};
 
 
static inline uint32_t wait_os_event(int time)
{
uint32_t val;
__asm__ __volatile__(
"int $0x40"
:"=a"(val)
:"a"(23),"b"(time));
return val;
};
 
 
int main(int argc, char *argv[])
{
OSMesaContext ctx;
void *buffer;
char *filename = NULL;
int ev;
int repeat=1;
 
/* Create an RGBA-mode context */
/* specify Z, stencil, accum sizes */
 
ctx = OSMesaCreateContextExt( OSMESA_RGBA, 16, 0, 0, NULL );
if (!ctx) {
printf("OSMesaCreateContext failed!\n");
return 0;
}
 
/* Allocate the image buffer */
buffer = malloc( Width * Height * 4 * sizeof(GLubyte) );
if (!buffer) {
printf("Alloc image buffer failed!\n");
return 0;
}
 
// __asm__ __volatile__("int3");
 
/* Bind the buffer to the context and make it current */
if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, Width, Height )) {
printf("OSMesaMakeCurrent failed!\n");
return 0;
}
 
{
int z, s, a;
glGetIntegerv(GL_DEPTH_BITS, &z);
glGetIntegerv(GL_STENCIL_BITS, &s);
glGetIntegerv(GL_ACCUM_RED_BITS, &a);
printf("Depth=%d Stencil=%d Accum=%d\n", z, s, a);
}
 
Reshape(Width, Height);
Init();
Draw();
 
printf("all done\n");
 
DrawWindow(10, 10, Width+9, Height+26, "OpenGL Engine Demo", 0x000000, 0x74);
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
 
while(repeat)
{
oskey_t key;
 
ev = wait_os_event(1);
switch(ev)
{
case 1:
DrawWindow(10, 10, Width+9, Width+26, NULL, 0x000000,0x74);
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
continue;
 
case 2:
key = get_key();
Key(key.code, 0, 0);
Draw();
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
continue;
 
case 3:
if(get_os_button()==1)
repeat=0;
continue;
};
Idle();
Draw();
Blit(buffer, 5, 22, 0, 0, Width, Height, Width,Height,Width*4);
};
 
/* free the image buffer */
free( buffer );
 
/* destroy the context */
OSMesaDestroyContext( ctx );
 
return 0;
}
 
int atexit(void (*func)(void))
{
return 0;
};
 
/contrib/sdk/samples/Mesa/quad.c
0,0 → 1,1155
/*
* 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.
*/
 
#include "gluos.h"
#include "gluint.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
 
/* Make it not a power of two to avoid cache thrashing on the chip */
#define CACHE_SIZE 240
 
#undef PI
#define PI 3.14159265358979323846
 
struct GLUquadric {
GLint normals;
GLboolean textureCoords;
GLint orientation;
GLint drawStyle;
void (GLAPIENTRY *errorCallback)( GLint );
};
 
GLUquadric * GLAPIENTRY
gluNewQuadric(void)
{
GLUquadric *newstate;
 
newstate = (GLUquadric *) malloc(sizeof(GLUquadric));
if (newstate == NULL) {
/* Can't report an error at this point... */
return NULL;
}
newstate->normals = GLU_SMOOTH;
newstate->textureCoords = GL_FALSE;
newstate->orientation = GLU_OUTSIDE;
newstate->drawStyle = GLU_FILL;
newstate->errorCallback = NULL;
return newstate;
}
 
 
void GLAPIENTRY
gluDeleteQuadric(GLUquadric *state)
{
free(state);
}
 
static void gluQuadricError(GLUquadric *qobj, GLenum which)
{
if (qobj->errorCallback) {
qobj->errorCallback(which);
}
}
 
void GLAPIENTRY
gluQuadricCallback(GLUquadric *qobj, GLenum which, _GLUfuncptr fn)
{
switch (which) {
case GLU_ERROR:
qobj->errorCallback = (void (GLAPIENTRY *)(GLint)) fn;
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
}
 
void GLAPIENTRY
gluQuadricNormals(GLUquadric *qobj, GLenum normals)
{
switch (normals) {
case GLU_SMOOTH:
case GLU_FLAT:
case GLU_NONE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->normals = normals;
}
 
void GLAPIENTRY
gluQuadricTexture(GLUquadric *qobj, GLboolean textureCoords)
{
qobj->textureCoords = textureCoords;
}
 
void GLAPIENTRY
gluQuadricOrientation(GLUquadric *qobj, GLenum orientation)
{
switch(orientation) {
case GLU_OUTSIDE:
case GLU_INSIDE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->orientation = orientation;
}
 
void GLAPIENTRY
gluQuadricDrawStyle(GLUquadric *qobj, GLenum drawStyle)
{
switch(drawStyle) {
case GLU_POINT:
case GLU_LINE:
case GLU_FILL:
case GLU_SILHOUETTE:
break;
default:
gluQuadricError(qobj, GLU_INVALID_ENUM);
return;
}
qobj->drawStyle = drawStyle;
}
 
void GLAPIENTRY
gluCylinder(GLUquadric *qobj, GLdouble baseRadius, GLdouble topRadius,
GLdouble height, GLint slices, GLint stacks)
{
GLint i,j;
GLfloat sinCache[CACHE_SIZE];
GLfloat cosCache[CACHE_SIZE];
GLfloat sinCache2[CACHE_SIZE];
GLfloat cosCache2[CACHE_SIZE];
GLfloat sinCache3[CACHE_SIZE];
GLfloat cosCache3[CACHE_SIZE];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat sintemp, costemp;
GLfloat length;
GLfloat deltaRadius;
GLfloat zNormal;
GLfloat xyNormalRatio;
GLfloat radiusLow, radiusHigh;
int needCache2, needCache3;
 
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
 
if (slices < 2 || stacks < 1 || baseRadius < 0.0 || topRadius < 0.0 ||
height < 0.0) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
 
/* Compute length (needed for normal calculations) */
deltaRadius = baseRadius - topRadius;
length = SQRT(deltaRadius*deltaRadius + height*height);
if (length == 0.0) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
 
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2 = needCache3 = 0;
if (qobj->normals == GLU_SMOOTH) {
needCache2 = 1;
}
 
if (qobj->normals == GLU_FLAT) {
if (qobj->drawStyle != GLU_POINT) {
needCache3 = 1;
}
if (qobj->drawStyle == GLU_LINE) {
needCache2 = 1;
}
}
 
zNormal = deltaRadius / length;
xyNormalRatio = height / length;
 
for (i = 0; i < slices; i++) {
angle = 2 * PI * i / slices;
if (needCache2) {
if (qobj->orientation == GLU_OUTSIDE) {
sinCache2[i] = xyNormalRatio * SIN(angle);
cosCache2[i] = xyNormalRatio * COS(angle);
} else {
sinCache2[i] = -xyNormalRatio * SIN(angle);
cosCache2[i] = -xyNormalRatio * COS(angle);
}
}
sinCache[i] = SIN(angle);
cosCache[i] = COS(angle);
}
 
if (needCache3) {
for (i = 0; i < slices; i++) {
angle = 2 * PI * (i-0.5) / slices;
if (qobj->orientation == GLU_OUTSIDE) {
sinCache3[i] = xyNormalRatio * SIN(angle);
cosCache3[i] = xyNormalRatio * COS(angle);
} else {
sinCache3[i] = -xyNormalRatio * SIN(angle);
cosCache3[i] = -xyNormalRatio * COS(angle);
}
}
}
 
sinCache[slices] = sinCache[0];
cosCache[slices] = cosCache[0];
if (needCache2) {
sinCache2[slices] = sinCache2[0];
cosCache2[slices] = cosCache2[0];
}
if (needCache3) {
sinCache3[slices] = sinCache3[0];
cosCache3[slices] = cosCache3[0];
}
 
switch (qobj->drawStyle) {
case GLU_FILL:
/* Note:
** An argument could be made for using a TRIANGLE_FAN for the end
** of the cylinder of either radii is 0.0 (a cone). However, a
** TRIANGLE_FAN would not work in smooth shading mode (the common
** case) because the normal for the apex is different for every
** triangle (and TRIANGLE_FAN doesn't let me respecify that normal).
** Now, my choice is GL_TRIANGLES, or leave the GL_QUAD_STRIP and
** just let the GL trivially reject one of the two triangles of the
** QUAD. GL_QUAD_STRIP is probably faster, so I will leave this code
** alone.
*/
for (j = 0; j < stacks; j++) {
zLow = j * height / stacks;
zHigh = (j + 1) * height / stacks;
radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
radiusHigh = baseRadius - deltaRadius * ((float) (j + 1) / stacks);
 
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sinCache3[i], cosCache3[i], zNormal);
break;
case GLU_SMOOTH:
glNormal3f(sinCache2[i], cosCache2[i], zNormal);
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], zLow);
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) (j+1) / stacks);
}
glVertex3f(radiusHigh * sinCache[i],
radiusHigh * cosCache[i], zHigh);
} else {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) (j+1) / stacks);
}
glVertex3f(radiusHigh * sinCache[i],
radiusHigh * cosCache[i], zHigh);
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], zLow);
}
}
glEnd();
}
break;
case GLU_POINT:
glBegin(GL_POINTS);
for (i = 0; i < slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
glNormal3f(sinCache2[i], cosCache2[i], zNormal);
break;
case GLU_NONE:
default:
break;
}
sintemp = sinCache[i];
costemp = cosCache[i];
for (j = 0; j <= stacks; j++) {
zLow = j * height / stacks;
radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
 
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sintemp,
radiusLow * costemp, zLow);
}
}
glEnd();
break;
case GLU_LINE:
for (j = 1; j < stacks; j++) {
zLow = j * height / stacks;
radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
 
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sinCache3[i], cosCache3[i], zNormal);
break;
case GLU_SMOOTH:
glNormal3f(sinCache2[i], cosCache2[i], zNormal);
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], zLow);
}
glEnd();
}
/* Intentionally fall through here... */
case GLU_SILHOUETTE:
for (j = 0; j <= stacks; j += stacks) {
zLow = j * height / stacks;
radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
 
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sinCache3[i], cosCache3[i], zNormal);
break;
case GLU_SMOOTH:
glNormal3f(sinCache2[i], cosCache2[i], zNormal);
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sinCache[i], radiusLow * cosCache[i],
zLow);
}
glEnd();
}
for (i = 0; i < slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
glNormal3f(sinCache2[i], cosCache2[i], 0.0);
break;
case GLU_NONE:
default:
break;
}
sintemp = sinCache[i];
costemp = cosCache[i];
glBegin(GL_LINE_STRIP);
for (j = 0; j <= stacks; j++) {
zLow = j * height / stacks;
radiusLow = baseRadius - deltaRadius * ((float) j / stacks);
 
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
(float) j / stacks);
}
glVertex3f(radiusLow * sintemp,
radiusLow * costemp, zLow);
}
glEnd();
}
break;
default:
break;
}
}
 
void GLAPIENTRY
gluDisk(GLUquadric *qobj, GLdouble innerRadius, GLdouble outerRadius,
GLint slices, GLint loops)
{
gluPartialDisk(qobj, innerRadius, outerRadius, slices, loops, 0.0, 360.0);
}
 
void GLAPIENTRY
gluPartialDisk(GLUquadric *qobj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle)
{
GLint i,j;
GLfloat sinCache[CACHE_SIZE];
GLfloat cosCache[CACHE_SIZE];
GLfloat angle;
GLfloat sintemp, costemp;
GLfloat deltaRadius;
GLfloat radiusLow, radiusHigh;
GLfloat texLow = 0.0, texHigh = 0.0;
GLfloat angleOffset;
GLint slices2;
GLint finish;
 
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
if (slices < 2 || loops < 1 || outerRadius <= 0.0 || innerRadius < 0.0 ||
innerRadius > outerRadius) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
 
if (sweepAngle < -360.0) sweepAngle = 360.0;
if (sweepAngle > 360.0) sweepAngle = 360.0;
if (sweepAngle < 0) {
startAngle += sweepAngle;
sweepAngle = -sweepAngle;
}
 
if (sweepAngle == 360.0) {
slices2 = slices;
} else {
slices2 = slices + 1;
}
 
/* Compute length (needed for normal calculations) */
deltaRadius = outerRadius - innerRadius;
 
/* Cache is the vertex locations cache */
 
angleOffset = startAngle / 180.0 * PI;
for (i = 0; i <= slices; i++) {
angle = angleOffset + ((PI * sweepAngle) / 180.0) * i / slices;
sinCache[i] = SIN(angle);
cosCache[i] = COS(angle);
}
 
if (sweepAngle == 360.0) {
sinCache[slices] = sinCache[0];
cosCache[slices] = cosCache[0];
}
 
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
if (qobj->orientation == GLU_OUTSIDE) {
glNormal3f(0.0, 0.0, 1.0);
} else {
glNormal3f(0.0, 0.0, -1.0);
}
break;
default:
case GLU_NONE:
break;
}
 
switch (qobj->drawStyle) {
case GLU_FILL:
if (innerRadius == 0.0) {
finish = loops - 1;
/* Triangle strip for inner polygons */
glBegin(GL_TRIANGLE_FAN);
if (qobj->textureCoords) {
glTexCoord2f(0.5, 0.5);
}
glVertex3f(0.0, 0.0, 0.0);
radiusLow = outerRadius -
deltaRadius * ((float) (loops-1) / loops);
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
}
 
if (qobj->orientation == GLU_OUTSIDE) {
for (i = slices; i >= 0; i--) {
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
}
} else {
for (i = 0; i <= slices; i++) {
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
}
}
glEnd();
} else {
finish = loops;
}
for (j = 0; j < finish; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops);
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
texHigh = radiusHigh / outerRadius / 2;
}
 
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
 
if (qobj->textureCoords) {
glTexCoord2f(texHigh * sinCache[i] + 0.5,
texHigh * cosCache[i] + 0.5);
}
glVertex3f(radiusHigh * sinCache[i],
radiusHigh * cosCache[i], 0.0);
} else {
if (qobj->textureCoords) {
glTexCoord2f(texHigh * sinCache[i] + 0.5,
texHigh * cosCache[i] + 0.5);
}
glVertex3f(radiusHigh * sinCache[i],
radiusHigh * cosCache[i], 0.0);
 
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
}
}
glEnd();
}
break;
case GLU_POINT:
glBegin(GL_POINTS);
for (i = 0; i < slices2; i++) {
sintemp = sinCache[i];
costemp = cosCache[i];
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
 
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
 
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
}
}
glEnd();
break;
case GLU_LINE:
if (innerRadius == outerRadius) {
glBegin(GL_LINE_STRIP);
 
for (i = 0; i <= slices; i++) {
if (qobj->textureCoords) {
glTexCoord2f(sinCache[i] / 2 + 0.5,
cosCache[i] / 2 + 0.5);
}
glVertex3f(innerRadius * sinCache[i],
innerRadius * cosCache[i], 0.0);
}
glEnd();
break;
}
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
}
 
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
}
glEnd();
}
for (i=0; i < slices2; i++) {
sintemp = sinCache[i];
costemp = cosCache[i];
glBegin(GL_LINE_STRIP);
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
}
 
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
}
glEnd();
}
break;
case GLU_SILHOUETTE:
if (sweepAngle < 360.0) {
for (i = 0; i <= slices; i+= slices) {
sintemp = sinCache[i];
costemp = cosCache[i];
glBegin(GL_LINE_STRIP);
for (j = 0; j <= loops; j++) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
 
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sintemp, radiusLow * costemp, 0.0);
}
glEnd();
}
}
for (j = 0; j <= loops; j += loops) {
radiusLow = outerRadius - deltaRadius * ((float) j / loops);
if (qobj->textureCoords) {
texLow = radiusLow / outerRadius / 2;
}
 
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
if (qobj->textureCoords) {
glTexCoord2f(texLow * sinCache[i] + 0.5,
texLow * cosCache[i] + 0.5);
}
glVertex3f(radiusLow * sinCache[i],
radiusLow * cosCache[i], 0.0);
}
glEnd();
if (innerRadius == outerRadius) break;
}
break;
default:
break;
}
}
 
void GLAPIENTRY
gluSphere(GLUquadric *qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLint i,j;
GLfloat sinCache1a[CACHE_SIZE];
GLfloat cosCache1a[CACHE_SIZE];
GLfloat sinCache2a[CACHE_SIZE];
GLfloat cosCache2a[CACHE_SIZE];
GLfloat sinCache3a[CACHE_SIZE];
GLfloat cosCache3a[CACHE_SIZE];
GLfloat sinCache1b[CACHE_SIZE];
GLfloat cosCache1b[CACHE_SIZE];
GLfloat sinCache2b[CACHE_SIZE];
GLfloat cosCache2b[CACHE_SIZE];
GLfloat sinCache3b[CACHE_SIZE];
GLfloat cosCache3b[CACHE_SIZE];
GLfloat angle;
GLfloat zLow, zHigh;
GLfloat sintemp1 = 0.0, sintemp2 = 0.0, sintemp3 = 0.0, sintemp4 = 0.0;
GLfloat costemp1 = 0.0, costemp2 = 0.0, costemp3 = 0.0, costemp4 = 0.0;
GLboolean needCache2, needCache3;
GLint start, finish;
 
if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
if (slices < 2 || stacks < 1 || radius < 0.0) {
gluQuadricError(qobj, GLU_INVALID_VALUE);
return;
}
 
/* Cache is the vertex locations cache */
/* Cache2 is the various normals at the vertices themselves */
/* Cache3 is the various normals for the faces */
needCache2 = needCache3 = GL_FALSE;
 
if (qobj->normals == GLU_SMOOTH) {
needCache2 = GL_TRUE;
}
 
if (qobj->normals == GLU_FLAT) {
if (qobj->drawStyle != GLU_POINT) {
needCache3 = GL_TRUE;
}
if (qobj->drawStyle == GLU_LINE) {
needCache2 = GL_TRUE;
}
}
 
for (i = 0; i < slices; i++) {
angle = 2 * PI * i / slices;
sinCache1a[i] = SIN(angle);
cosCache1a[i] = COS(angle);
if (needCache2) {
sinCache2a[i] = sinCache1a[i];
cosCache2a[i] = cosCache1a[i];
}
}
 
for (j = 0; j <= stacks; j++) {
angle = PI * j / stacks;
if (needCache2) {
if (qobj->orientation == GLU_OUTSIDE) {
sinCache2b[j] = SIN(angle);
cosCache2b[j] = COS(angle);
} else {
sinCache2b[j] = -SIN(angle);
cosCache2b[j] = -COS(angle);
}
}
sinCache1b[j] = radius * SIN(angle);
cosCache1b[j] = radius * COS(angle);
}
/* Make sure it comes to a point */
sinCache1b[0] = 0;
sinCache1b[stacks] = 0;
 
if (needCache3) {
for (i = 0; i < slices; i++) {
angle = 2 * PI * (i-0.5) / slices;
sinCache3a[i] = SIN(angle);
cosCache3a[i] = COS(angle);
}
for (j = 0; j <= stacks; j++) {
angle = PI * (j - 0.5) / stacks;
if (qobj->orientation == GLU_OUTSIDE) {
sinCache3b[j] = SIN(angle);
cosCache3b[j] = COS(angle);
} else {
sinCache3b[j] = -SIN(angle);
cosCache3b[j] = -COS(angle);
}
}
}
 
sinCache1a[slices] = sinCache1a[0];
cosCache1a[slices] = cosCache1a[0];
if (needCache2) {
sinCache2a[slices] = sinCache2a[0];
cosCache2a[slices] = cosCache2a[0];
}
if (needCache3) {
sinCache3a[slices] = sinCache3a[0];
cosCache3a[slices] = cosCache3a[0];
}
 
switch (qobj->drawStyle) {
case GLU_FILL:
/* Do ends of sphere as TRIANGLE_FAN's (if not texturing)
** We don't do it when texturing because we need to respecify the
** texture coordinates of the apex for every adjacent vertex (because
** it isn't a constant for that point)
*/
if (!(qobj->textureCoords)) {
start = 1;
finish = stacks - 1;
 
/* Low end first (j == 0 iteration) */
sintemp2 = sinCache1b[1];
zHigh = cosCache1b[1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp3 = sinCache3b[1];
costemp3 = cosCache3b[1];
break;
case GLU_SMOOTH:
sintemp3 = sinCache2b[1];
costemp3 = cosCache2b[1];
glNormal3f(sinCache2a[0] * sinCache2b[0],
cosCache2a[0] * sinCache2b[0],
cosCache2b[0]);
break;
default:
break;
}
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, radius);
if (qobj->orientation == GLU_OUTSIDE) {
for (i = slices; i >= 0; i--) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
if (i != slices) {
glNormal3f(sinCache3a[i+1] * sintemp3,
cosCache3a[i+1] * sintemp3,
costemp3);
}
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
} else {
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
 
/* High end next (j == stacks-1 iteration) */
sintemp2 = sinCache1b[stacks-1];
zHigh = cosCache1b[stacks-1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp3 = sinCache3b[stacks];
costemp3 = cosCache3b[stacks];
break;
case GLU_SMOOTH:
sintemp3 = sinCache2b[stacks-1];
costemp3 = cosCache2b[stacks-1];
glNormal3f(sinCache2a[stacks] * sinCache2b[stacks],
cosCache2a[stacks] * sinCache2b[stacks],
cosCache2b[stacks]);
break;
default:
break;
}
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, -radius);
if (qobj->orientation == GLU_OUTSIDE) {
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp3,
cosCache3a[i] * sintemp3,
costemp3);
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
} else {
for (i = slices; i >= 0; i--) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
if (i != slices) {
glNormal3f(sinCache3a[i+1] * sintemp3,
cosCache3a[i+1] * sintemp3,
costemp3);
}
break;
case GLU_NONE:
default:
break;
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
} else {
start = 0;
finish = stacks;
}
for (j = start; j < finish; j++) {
zLow = cosCache1b[j];
zHigh = cosCache1b[j+1];
sintemp1 = sinCache1b[j];
sintemp2 = sinCache1b[j+1];
switch(qobj->normals) {
case GLU_FLAT:
sintemp4 = sinCache3b[j+1];
costemp4 = cosCache3b[j+1];
break;
case GLU_SMOOTH:
if (qobj->orientation == GLU_OUTSIDE) {
sintemp3 = sinCache2b[j+1];
costemp3 = cosCache2b[j+1];
sintemp4 = sinCache2b[j];
costemp4 = cosCache2b[j];
} else {
sintemp3 = sinCache2b[j];
costemp3 = cosCache2b[j];
sintemp4 = sinCache2b[j+1];
costemp4 = cosCache2b[j+1];
}
break;
default:
break;
}
 
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp3,
cosCache2a[i] * sintemp3,
costemp3);
break;
case GLU_FLAT:
case GLU_NONE:
default:
break;
}
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
} else {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], zLow);
}
switch(qobj->normals) {
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp4,
cosCache2a[i] * sintemp4,
costemp4);
break;
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp4,
cosCache3a[i] * sintemp4,
costemp4);
break;
case GLU_NONE:
default:
break;
}
if (qobj->orientation == GLU_OUTSIDE) {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], zLow);
} else {
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) (j+1) / stacks);
}
glVertex3f(sintemp2 * sinCache1a[i],
sintemp2 * cosCache1a[i], zHigh);
}
}
glEnd();
}
break;
case GLU_POINT:
glBegin(GL_POINTS);
for (j = 0; j <= stacks; j++) {
sintemp1 = sinCache1b[j];
costemp1 = cosCache1b[j];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
default:
break;
}
for (i = 0; i < slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp2,
cosCache2a[i] * sintemp2,
costemp2);
break;
case GLU_NONE:
default:
break;
}
 
zLow = j * radius / stacks;
 
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
}
}
glEnd();
break;
case GLU_LINE:
case GLU_SILHOUETTE:
for (j = 1; j < stacks; j++) {
sintemp1 = sinCache1b[j];
costemp1 = cosCache1b[j];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2b[j];
costemp2 = cosCache2b[j];
break;
default:
break;
}
 
glBegin(GL_LINE_STRIP);
for (i = 0; i <= slices; i++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sinCache3a[i] * sintemp2,
cosCache3a[i] * sintemp2,
costemp2);
break;
case GLU_SMOOTH:
glNormal3f(sinCache2a[i] * sintemp2,
cosCache2a[i] * sintemp2,
costemp2);
break;
case GLU_NONE:
default:
break;
}
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1a[i],
sintemp1 * cosCache1a[i], costemp1);
}
glEnd();
}
for (i = 0; i < slices; i++) {
sintemp1 = sinCache1a[i];
costemp1 = cosCache1a[i];
switch(qobj->normals) {
case GLU_FLAT:
case GLU_SMOOTH:
sintemp2 = sinCache2a[i];
costemp2 = cosCache2a[i];
break;
default:
break;
}
 
glBegin(GL_LINE_STRIP);
for (j = 0; j <= stacks; j++) {
switch(qobj->normals) {
case GLU_FLAT:
glNormal3f(sintemp2 * sinCache3b[j],
costemp2 * sinCache3b[j],
cosCache3b[j]);
break;
case GLU_SMOOTH:
glNormal3f(sintemp2 * sinCache2b[j],
costemp2 * sinCache2b[j],
cosCache2b[j]);
break;
case GLU_NONE:
default:
break;
}
 
if (qobj->textureCoords) {
glTexCoord2f(1 - (float) i / slices,
1 - (float) j / stacks);
}
glVertex3f(sintemp1 * sinCache1b[j],
costemp1 * sinCache1b[j], cosCache1b[j]);
}
glEnd();
}
break;
default:
break;
}
}
/contrib/sdk/samples/Mesa/readtex.c
0,0 → 1,494
/* readtex.c */
 
/*
* Read an SGI .rgb image file and generate a mipmap texture set.
* Much of this code was borrowed from SGI's tk OpenGL toolkit.
*/
 
 
 
#include <GL/gl.h>
#include <GL/glu.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "readtex.h"
 
 
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
 
 
/*
** RGB Image Structure
*/
 
typedef struct _TK_RGBImageRec {
GLint sizeX, sizeY;
GLint components;
unsigned char *data;
} TK_RGBImageRec;
 
 
 
/******************************************************************************/
 
typedef struct _rawImageRec {
unsigned short imagic;
unsigned short type;
unsigned short dim;
unsigned short sizeX, sizeY, sizeZ;
unsigned long min, max;
unsigned long wasteBytes;
char name[80];
unsigned long colorMap;
FILE *file;
unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
unsigned long rleEnd;
GLuint *rowStart;
GLint *rowSize;
} rawImageRec;
 
/******************************************************************************/
 
static void ConvertShort(unsigned short *array, long length)
{
unsigned long b1, b2;
unsigned char *ptr;
 
ptr = (unsigned char *)array;
while (length--) {
b1 = *ptr++;
b2 = *ptr++;
*array++ = (unsigned short) ((b1 << 8) | (b2));
}
}
 
static void ConvertLong(GLuint *array, long length)
{
unsigned long b1, b2, b3, b4;
unsigned char *ptr;
 
ptr = (unsigned char *)array;
while (length--) {
b1 = *ptr++;
b2 = *ptr++;
b3 = *ptr++;
b4 = *ptr++;
*array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
}
}
 
static rawImageRec *RawImageOpen(const char *fileName)
{
union {
int testWord;
char testByte[4];
} endianTest;
rawImageRec *raw;
GLenum swapFlag;
int x;
size_t result;
 
endianTest.testWord = 1;
if (endianTest.testByte[0] == 1) {
swapFlag = GL_TRUE;
} else {
swapFlag = GL_FALSE;
}
 
raw = (rawImageRec *)calloc(1, sizeof(rawImageRec));
if (raw == NULL) {
fprintf(stderr, "Out of memory!\n");
return NULL;
}
raw->file = fopen(fileName, "rb");
if (raw->file == NULL) {
const char *baseName = strrchr(fileName, '/');
if(baseName)
raw->file = fopen(baseName + 1, "rb");
if(raw->file == NULL) {
free(raw);
return NULL;
}
}
 
result = fread(raw, 1, 12, raw->file);
assert(result == 12);
 
if (swapFlag) {
ConvertShort(&raw->imagic, 1);
ConvertShort(&raw->type, 1);
ConvertShort(&raw->dim, 1);
ConvertShort(&raw->sizeX, 1);
ConvertShort(&raw->sizeY, 1);
ConvertShort(&raw->sizeZ, 1);
}
 
raw->tmp = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpR = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpG = (unsigned char *)malloc(raw->sizeX*256);
raw->tmpB = (unsigned char *)malloc(raw->sizeX*256);
if (raw->sizeZ==4) {
raw->tmpA = (unsigned char *)malloc(raw->sizeX*256);
}
if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||
raw->tmpB == NULL) {
fprintf(stderr, "Out of memory!\n");
free(raw->tmp);
free(raw->tmpR);
free(raw->tmpG);
free(raw->tmpB);
free(raw->tmpA);
free(raw);
return NULL;
}
 
if ((raw->type & 0xFF00) == 0x0100) {
x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
raw->rowStart = (GLuint *)malloc(x);
raw->rowSize = (GLint *)malloc(x);
if (raw->rowStart == NULL || raw->rowSize == NULL) {
fprintf(stderr, "Out of memory!\n");
free(raw->tmp);
free(raw->tmpR);
free(raw->tmpG);
free(raw->tmpB);
free(raw->tmpA);
free(raw->rowStart);
free(raw->rowSize);
free(raw);
return NULL;
}
raw->rleEnd = 512 + (2 * x);
fseek(raw->file, 512, SEEK_SET);
result = fread(raw->rowStart, 1, x, raw->file);
assert(result == x);
result = fread(raw->rowSize, 1, x, raw->file);
assert(result == x);
if (swapFlag) {
ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
}
}
return raw;
}
 
static void RawImageClose(rawImageRec *raw)
{
fclose(raw->file);
free(raw->tmp);
free(raw->tmpR);
free(raw->tmpG);
free(raw->tmpB);
if (raw->rowStart)
free(raw->rowStart);
if (raw->rowSize)
free(raw->rowSize);
if (raw->sizeZ>3) {
free(raw->tmpA);
}
free(raw);
}
 
static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
{
unsigned char *iPtr, *oPtr, pixel;
int count, done = 0;
size_t result;
 
if ((raw->type & 0xFF00) == 0x0100) {
fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET);
result = fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY],
raw->file);
assert(result == (unsigned int)raw->rowSize[y+z*raw->sizeY]);
 
iPtr = raw->tmp;
oPtr = buf;
while (!done) {
pixel = *iPtr++;
count = (int)(pixel & 0x7F);
if (!count) {
done = 1;
return;
}
if (pixel & 0x80) {
while (count--) {
*oPtr++ = *iPtr++;
}
} else {
pixel = *iPtr++;
while (count--) {
*oPtr++ = pixel;
}
}
}
} else {
fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY),
SEEK_SET);
result = fread(buf, 1, raw->sizeX, raw->file);
assert(result == raw->sizeX);
}
}
 
 
static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final)
{
unsigned char *ptr;
int i, j;
 
final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4);
if (final->data == NULL) {
fprintf(stderr, "Out of memory!\n");
return;
}
 
ptr = final->data;
for (i = 0; i < (int)(raw->sizeY); i++) {
RawImageGetRow(raw, raw->tmpR, i, 0);
RawImageGetRow(raw, raw->tmpG, i, 1);
RawImageGetRow(raw, raw->tmpB, i, 2);
if (raw->sizeZ>3) {
RawImageGetRow(raw, raw->tmpA, i, 3);
}
for (j = 0; j < (int)(raw->sizeX); j++) {
*ptr++ = *(raw->tmpR + j);
*ptr++ = *(raw->tmpG + j);
*ptr++ = *(raw->tmpB + j);
if (raw->sizeZ>3) {
*ptr++ = *(raw->tmpA + j);
}
}
}
}
 
 
static TK_RGBImageRec *tkRGBImageLoad(const char *fileName)
{
rawImageRec *raw;
TK_RGBImageRec *final;
 
raw = RawImageOpen(fileName);
if (!raw) {
fprintf(stderr, "File not found\n");
return NULL;
}
final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec));
if (final == NULL) {
fprintf(stderr, "Out of memory!\n");
RawImageClose(raw);
return NULL;
}
final->sizeX = raw->sizeX;
final->sizeY = raw->sizeY;
final->components = raw->sizeZ;
RawImageGetData(raw, final);
RawImageClose(raw);
return final;
}
 
 
static void FreeImage( TK_RGBImageRec *image )
{
free(image->data);
free(image);
}
 
 
/*
* Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
* Input: imageFile - name of .rgb to read
* intFormat - internal texture format to use, or number of components
* Return: GL_TRUE if success, GL_FALSE if error.
*/
GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat )
{
GLint w, h;
return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h );
}
 
 
 
GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target,
GLint intFormat, GLint *width, GLint *height )
{
GLint error;
GLenum format;
TK_RGBImageRec *image;
 
image = tkRGBImageLoad( imageFile );
if (!image) {
return GL_FALSE;
}
 
if (image->components==3) {
format = GL_RGB;
}
else if (image->components==4) {
format = GL_RGBA;
}
else {
/* not implemented */
fprintf(stderr,
"Error in LoadRGBMipmaps %d-component images not implemented\n",
image->components );
FreeImage(image);
return GL_FALSE;
}
 
error = gluBuild2DMipmaps( target,
intFormat,
image->sizeX, image->sizeY,
format,
GL_UNSIGNED_BYTE,
image->data );
 
*width = image->sizeX;
*height = image->sizeY;
 
FreeImage(image);
 
return error ? GL_FALSE : GL_TRUE;
}
 
 
 
/*
* Load an SGI .rgb file and return a pointer to the image data.
* Input: imageFile - name of .rgb to read
* Output: width - width of image
* height - height of image
* format - format of image (GL_RGB or GL_RGBA)
* Return: pointer to image data or NULL if error
*/
GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height,
GLenum *format )
{
TK_RGBImageRec *image;
GLint bytes;
GLubyte *buffer;
 
image = tkRGBImageLoad( imageFile );
if (!image) {
return NULL;
}
 
if (image->components==3) {
*format = GL_RGB;
}
else if (image->components==4) {
*format = GL_RGBA;
}
else {
/* not implemented */
fprintf(stderr,
"Error in LoadRGBImage %d-component images not implemented\n",
image->components );
FreeImage(image);
return NULL;
}
 
*width = image->sizeX;
*height = image->sizeY;
 
bytes = image->sizeX * image->sizeY * image->components;
buffer = (GLubyte *) malloc(bytes);
if (!buffer) {
FreeImage(image);
return NULL;
}
 
memcpy( (void *) buffer, (void *) image->data, bytes );
 
FreeImage(image);
 
return buffer;
}
 
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
 
 
static void ConvertRGBtoYUV(GLint w, GLint h, GLint texel_bytes,
const GLubyte *src,
GLushort *dest)
{
GLint i, j;
 
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
const GLfloat r = (src[0]) / 255.0;
const GLfloat g = (src[1]) / 255.0;
const GLfloat b = (src[2]) / 255.0;
GLfloat y, cr, cb;
GLint iy, icr, icb;
 
y = r * 65.481 + g * 128.553 + b * 24.966 + 16;
cb = r * -37.797 + g * -74.203 + b * 112.0 + 128;
cr = r * 112.0 + g * -93.786 + b * -18.214 + 128;
/*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/
iy = (GLint) CLAMP(y, 0, 254);
icb = (GLint) CLAMP(cb, 0, 254);
icr = (GLint) CLAMP(cr, 0, 254);
 
if (j & 1) {
/* odd */
*dest = (iy << 8) | icr;
}
else {
/* even */
*dest = (iy << 8) | icb;
}
dest++;
src += texel_bytes;
}
}
}
 
 
/*
* Load an SGI .rgb file and return a pointer to the image data, converted
* to 422 yuv.
*
* Input: imageFile - name of .rgb to read
* Output: width - width of image
* height - height of image
* Return: pointer to image data or NULL if error
*/
GLushort *LoadYUVImage( const char *imageFile, GLint *width, GLint *height )
{
TK_RGBImageRec *image;
GLushort *buffer;
 
image = tkRGBImageLoad( imageFile );
if (!image) {
return NULL;
}
 
if (image->components != 3 && image->components !=4 ) {
/* not implemented */
fprintf(stderr,
"Error in LoadYUVImage %d-component images not implemented\n",
image->components );
FreeImage(image);
return NULL;
}
 
*width = image->sizeX;
*height = image->sizeY;
 
buffer = (GLushort *) malloc( image->sizeX * image->sizeY * 2 );
 
if (buffer)
ConvertRGBtoYUV( image->sizeX,
image->sizeY,
image->components,
image->data,
buffer );
 
 
FreeImage(image);
return buffer;
}
 
/contrib/sdk/samples/Mesa/readtex.h
0,0 → 1,26
/* readtex.h */
 
#ifndef READTEX_H
#define READTEX_H
 
 
#include <GL/gl.h>
 
 
extern GLboolean
LoadRGBMipmaps( const char *imageFile, GLint intFormat );
 
 
extern GLboolean
LoadRGBMipmaps2( const char *imageFile, GLenum target,
GLint intFormat, GLint *width, GLint *height );
 
 
extern GLubyte *
LoadRGBImage( const char *imageFile,
GLint *width, GLint *height, GLenum *format );
 
extern GLushort *
LoadYUVImage( const char *imageFile, GLint *width, GLint *height );
 
#endif
/contrib/sdk/samples/Mesa/reflect.rgb
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/contrib/sdk/samples/Mesa/shaderutil.h
0,0 → 1,63
#ifndef SHADER_UTIL_H
#define SHADER_UTIL_H
 
 
 
struct uniform_info
{
const char *name;
GLuint size; /**< number of value[] elements: 1, 2, 3 or 4 */
GLenum type; /**< GL_FLOAT, GL_FLOAT_VEC4, GL_INT, etc */
GLfloat value[4];
GLint location; /**< filled in by InitUniforms() */
};
 
#define END_OF_UNIFORMS { NULL, 0, GL_NONE, { 0, 0, 0, 0 }, -1 }
 
 
struct attrib_info
{
const char *name;
GLuint size; /**< number of value[] elements: 1, 2, 3 or 4 */
GLenum type; /**< GL_FLOAT, GL_FLOAT_VEC4, GL_INT, etc */
GLint location;
};
 
 
extern GLboolean
ShadersSupported(void);
 
extern GLuint
CompileShaderText(GLenum shaderType, const char *text);
 
extern GLuint
CompileShaderFile(GLenum shaderType, const char *filename);
 
extern GLuint
LinkShaders(GLuint vertShader, GLuint fragShader);
 
extern GLboolean
ValidateShaderProgram(GLuint program);
 
extern GLdouble
GetShaderCompileTime(void);
 
extern GLdouble
GetShaderLinkTime(void);
 
extern void
SetUniformValues(GLuint program, struct uniform_info uniforms[]);
 
extern GLuint
GetUniforms(GLuint program, struct uniform_info uniforms[]);
 
extern void
PrintUniforms(const struct uniform_info uniforms[]);
 
extern GLuint
GetAttribs(GLuint program, struct attrib_info attribs[]);
 
extern void
PrintAttribs(const struct attrib_info attribs[]);
 
#endif /* SHADER_UTIL_H */