windows-nt/Source/XPSP1/NT/multimedia/opengl/test/auxprogs/rgb/vaperf.c
2020-09-26 16:20:57 +08:00

1556 lines
37 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <float.h>
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
// #define PROFILE 1
#ifdef PROFILE
#include <icapexp.h>
#endif
typedef struct
{
float x, y, z;
float nx, ny, nz;
float tu, tv;
DWORD color;
} D3DVERTEX;
typedef D3DVERTEX *LPD3DVERTEX;
typedef struct
{
int v1;
int v2;
int v3;
} D3DTRIANGLE;
typedef D3DTRIANGLE *LPD3DTRIANGLE;
#define D3DVAL(f) ((float)(f))
#define RGB_MAKE(r, g, b) \
(((DWORD)((r) & 0xff) << 0) | \
((DWORD)((g) & 0xff) << 8) | \
((DWORD)((b) & 0xff) << 16) | \
((DWORD)(0xff) << 24))
typedef float __GLfloat;
typedef struct
{
__GLfloat matrix[4][4];
} __GLmatrix;
__GLmatrix identity =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
void __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
{
__GLfloat b00, b01, b02, b03;
__GLfloat b10, b11, b12, b13;
__GLfloat b20, b21, b22, b23;
__GLfloat b30, b31, b32, b33;
GLint i;
b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
b32 = b->matrix[3][2]; b33 = b->matrix[3][3];
for (i = 0; i < 4; i++) {
r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
+ a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
+ a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
+ a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
+ a->matrix[i][2]*b23 + a->matrix[i][3]*b33;
}
}
void MakePosMatrix(__GLmatrix *lpM, float x, float y, float z)
{
memcpy(lpM, &identity, sizeof(__GLmatrix));
lpM->matrix[3][0] = D3DVAL(x);
lpM->matrix[3][1] = D3DVAL(y);
lpM->matrix[3][2] = D3DVAL(z);
}
void MakeRotMatrix(__GLmatrix *lpM, float rx, float ry, float rz)
{
float ct, st;
__GLmatrix My, Mx, Mz, T;
memcpy(&My, &identity, sizeof(__GLmatrix));
ct = D3DVAL(cos(ry));
st = D3DVAL(sin(ry));
My.matrix[0][0] = ct;
My.matrix[0][2] = -st;
My.matrix[2][0] = st;
My.matrix[2][2] = ct;
memcpy(&Mx, &identity, sizeof(__GLmatrix));
ct = D3DVAL(cos(rx));
st = D3DVAL(sin(rx));
Mx.matrix[1][1] = ct;
Mx.matrix[1][2] = st;
Mx.matrix[2][1] = -st;
Mx.matrix[2][2] = ct;
memcpy(&Mz, &identity, sizeof(__GLmatrix));
ct = D3DVAL(cos(rz));
st = D3DVAL(sin(rz));
Mz.matrix[0][0] = ct;
Mz.matrix[0][1] = st;
Mz.matrix[1][0] = -st;
Mz.matrix[1][1] = ct;
__glMultMatrix(&T, &My, &Mx);
__glMultMatrix(lpM, &T, &Mz);
}
void *Malloc(size_t bytes)
{
void *pv;
pv = malloc(bytes);
if (pv == NULL)
{
printf("Unable to alloc %d bytes\n", bytes);
exit(1);
}
return pv;
}
#define PI ((float)3.14159265358979323846)
#define WIDTH 400
#define HEIGHT 400
#define SPWIDTH 140
#define SPHEIGHT 140
#define MAWIDTH 90
#define MAHEIGHT 75
#define LAWIDTH 230
#define LAHEIGHT 190
int iSwapWidth, iSwapHeight;
#define SRADIUS 0.4f
#define DMINUSR 0.6
#define DV 0.05
#define DR 0.3
#define DEPTH 0.6f
#define random(x) (((float)rand() / RAND_MAX) * (x))
#define FILL_TRIANGLES 50
#define MEDIUM_AREA 3000
#define LARGE_AREA 20000
#define FRONT_TO_BACK 0
#define BACK_TO_FRONT 1
#define ORDER_COUNT 2
int iOrder = FRONT_TO_BACK;
char *pszOrders[] =
{
"front-to-back",
"back-to-front"
};
#define AREA_LARGE 0
#define AREA_MEDIUM 1
#define AREA_COUNT 2
int iFillSize = AREA_MEDIUM;
int iTriangleArea;
typedef struct _Sphere
{
GLfloat xrv, yrv, zrv;
__GLmatrix pos, dpos;
__GLmatrix rot, drot;
} Sphere;
#define NSPHERES 8
Sphere spheres[NSPHERES];
BOOL fSingle = FALSE;
BOOL fRotate = TRUE;
BOOL fBounce = TRUE;
BOOL fSwap = TRUE;
BOOL fPaused = FALSE;
BOOL fUseScissor = TRUE;
BOOL fSpread = FALSE;
BOOL fExit = FALSE;
BOOL fSingleColor = TRUE;
BOOL fVerbose = FALSE;
BOOL fDisplayList = TRUE;
int iMultiLoop = 1;
int nRings = 30;
int nSections = 30;
GLint iDlist;
#define TEXOBJ
#ifdef TEXOBJ
GLuint uiTexObj;
#endif
PFNGLADDSWAPHINTRECTWINPROC glAddSwapHintRectWIN;
#define TEST_FILL 0
#define TEST_POLYS 1
#define TEST_COUNT 2
int iTest = TEST_POLYS;
AUX_RGBImageRec *pTexture;
#define TEXMODE_REPLACE 0
#define TEXMODE_DECAL 1
#define TEXMODE_MODULATE 2
#define TEXMODE_COUNT 3
int iTexMode = TEXMODE_REPLACE;
char *pszTexModes[] =
{
"replace", "decal", "modulate"
};
GLenum eTexModes[] =
{
GL_REPLACE, GL_DECAL, GL_MODULATE
};
BOOL fPerspective = TRUE;
//--------------------------------------------------------------------------;
//
// FunctionName: GenerateSphere()
//
// Purpose:
// Generate the geometry of a sphere.
//
// Returns BOOL
//
// History:
// 11/17/95 RichGr
//
//--------------------------------------------------------------------------;
/*
* Generates a sphere around the y-axis centered at the origin including
* normals and texture coordinates. Returns TRUE on success and FALSE on
* failure.
* sphere_r Radius of the sphere.
* num_rings Number of full rings not including the top and bottom
* caps.
* num_sections Number of sections each ring is divided into. Each
* section contains two triangles on full rings and one
* on top and bottom caps.
* sx, sy, sz Scaling along each axis. Set each to 1.0 for a
* perfect sphere.
* plpv On exit points to the vertices of the sphere. The
* function allocates this space. Not allocated if
* function fails.
* plptri On exit points to the triangles of the sphere which
* reference vertices in the vertex list. The function
* allocates this space. Not allocated if function fails.
* pnum_v On exit contains the number of vertices.
* pnum_tri On exit contains the number of triangles.
*/
BOOL GenerateSphere(float sphere_r, int num_rings, int num_sections,
float sx, float sy, float sz, LPD3DVERTEX* plpv,
LPD3DTRIANGLE* plptri, int* pnum_v, int* pnum_tri)
{
float theta, phi; /* Angles used to sweep around sphere */
float dtheta, dphi; /* Angle between each section and ring */
float x, y, z, v, rsintheta; /* Temporary variables */
int i, j, n, m; /* counters */
int num_v, num_tri; /* Internal vertex and triangle count */
LPD3DVERTEX lpv; /* Internal pointer for vertices */
LPD3DTRIANGLE lptri; /* Internal pointer for trianlges */
/*
* Check the parameters to make sure they are valid.
*/
if ((sphere_r <= 0)
|| (num_rings < 1)
|| (num_sections < 3)
|| (sx <= 0) || (sy <= 0) || (sz <= 0))
return FALSE;
/*
* Generate space for the required triangles and vertices.
*/
num_tri = (num_rings + 1) * num_sections * 2;
num_v = (num_rings + 1) * num_sections + 2;
*plpv = (LPD3DVERTEX)Malloc(sizeof(D3DVERTEX) * num_v);
*plptri = (LPD3DTRIANGLE)Malloc(sizeof(D3DTRIANGLE) * num_tri);
lpv = *plpv;
lptri = *plptri;
*pnum_v = num_v;
*pnum_tri = num_tri;
/*
* Generate vertices at the top and bottom points.
*/
lpv[0].x = D3DVAL(0.0f);
lpv[0].y = D3DVAL(sy * sphere_r);
lpv[0].z = D3DVAL(0.0f);
lpv[0].nx = D3DVAL(0.0f);
lpv[0].ny = D3DVAL(1.0f);
lpv[0].nz = D3DVAL(0.0f);
lpv[0].color = RGB_MAKE(0, 0, 255);
lpv[0].tu = D3DVAL(0.0f);
lpv[0].tv = D3DVAL(0.0f);
lpv[num_v - 1].x = D3DVAL(0.0f);
lpv[num_v - 1].y = D3DVAL(sy * -sphere_r);
lpv[num_v - 1].z = D3DVAL(0.0f);
lpv[num_v - 1].nx = D3DVAL(0.0f);
lpv[num_v - 1].ny = D3DVAL(-1.0f);
lpv[num_v - 1].nz = D3DVAL(0.0f);
lpv[num_v - 1].tu = D3DVAL(0.0f);
lpv[num_v - 1].tv = D3DVAL(1.0f);
lpv[num_v - 1].color = RGB_MAKE(0, 255, 0);
/*
* Generate vertex points for rings
*/
dtheta = PI / (float) (num_rings + 2);
dphi = 2.0f * PI / (float) num_sections;
n = 1; /* vertex being generated, begins at 1 to skip top point */
theta = dtheta;
for (i = 0; i <= num_rings; i++)
{
y = (float)(sphere_r * cos(theta)); /* y is the same for each ring */
v = theta / PI; /* v is the same for each ring */
rsintheta = (float)(sphere_r * sin(theta));
phi = 0.0f;
for (j = 0; j < num_sections; j++)
{
x = (float)(rsintheta * sin(phi));
z = (float)(rsintheta * cos(phi));
lpv[n].x = D3DVAL(sx * x);
lpv[n].z = D3DVAL(sz * z);
lpv[n].y = D3DVAL(sy * y);
lpv[n].nx = D3DVAL(x / sphere_r);
lpv[n].ny = D3DVAL(y / sphere_r);
lpv[n].nz = D3DVAL(z / sphere_r);
lpv[n].tv = D3DVAL(v);
lpv[n].tu = D3DVAL(1.0f - phi / (2.0f * PI));
if (n & 1)
{
lpv[n].color = RGB_MAKE(0, 0, 255);
}
else
{
lpv[n].color = RGB_MAKE(0, 255, 0);
}
phi += dphi;
++n;
}
theta += dtheta;
}
/*
* Generate triangles for top and bottom caps.
*/
for (i = 0; i < num_sections; i++)
{
lptri[i].v1 = 0;
lptri[i].v2 = i + 1;
lptri[i].v3 = 1 + ((i + 1) % num_sections);
// lptri[i].flags = D3D_EDGE_ENABLE_TRIANGLE;
lptri[num_tri - num_sections + i].v1 = num_v - 1;
lptri[num_tri - num_sections + i].v2 = num_v - 2 - i;
lptri[num_tri - num_sections + i].v3 = num_v - 2 - ((1 + i) % num_sections);
// lptri[num_tri - num_sections + i].flags= D3D_EDGE_ENABLE_TRIANGLE;
}
/*
* Generate triangles for the rings
*/
m = 1; /* first vertex in current ring,begins at 1 to skip top point*/
n = num_sections; /* triangle being generated, skip the top cap */
for (i = 0; i < num_rings; i++)
{
for (j = 0; j < num_sections; j++)
{
lptri[n].v1 = m + j;
lptri[n].v2 = m + num_sections + j;
lptri[n].v3 = m + num_sections + ((j + 1) % num_sections);
// lptri[n].flags = D3D_EDGE_ENABLE_TRIANGLE;
lptri[n + 1].v1 = lptri[n].v1;
lptri[n + 1].v2 = lptri[n].v3;
lptri[n + 1].v3 = m + ((j + 1) % num_sections);
// lptri[n + 1].flags = D3D_EDGE_ENABLE_TRIANGLE;
n += 2;
}
m += num_sections;
}
return TRUE;
}
// Creates triangle and quad strip index sets for vertex data generated
// by GenerateSphere. The top and bottom triangle fans are omitted because
// they're degenerate cases for strips
int CreateStrip(int nSections, int **ppiStrip)
{
int nPts;
int *piIdx, iIdxBase;
int iRing, iSection;
// Stick to a single strip for now
nRings = 1;
nPts = nRings*(nSections+1)*2;
*ppiStrip = (int *)Malloc(sizeof(int)*nPts);
piIdx = *ppiStrip;
iIdxBase = 1;
for (iRing = 0; iRing < nRings; iRing++)
{
for (iSection = 0; iSection <= nSections; iSection++)
{
*piIdx++ = iIdxBase+(iSection % nSections);
*piIdx++ = iIdxBase+(iSection % nSections)+nSections;
}
iIdxBase += nSections;
}
return nPts;
}
float fltCenter[NSPHERES][2] =
{
-SRADIUS, 0.0f,
0.0f, SRADIUS,
SRADIUS, 0.0f,
0.0f, -SRADIUS
};
void InitSpheres(void)
{
int i;
Sphere *sp;
float x, y, z;
#if 0
srand(time(NULL));
#else
srand( (unsigned)8269362521);
#endif
for (i = 0; i < NSPHERES; i++)
{
sp = &spheres[i];
if (fBounce)
{
x = (float)DMINUSR - (float)random(2 * DMINUSR);
y = (float)DMINUSR - (float)random(2 * DMINUSR);
z = (float)-DEPTH + (float)random(2 * DEPTH);
}
else
{
x = fltCenter[i][0];
y = fltCenter[i][1];
z = 0.0f;
}
MakePosMatrix(&sp->pos, x, y, z);
x = (float)DV - (float)random(2 * DV);
y = (float)DV - (float)random(2 * DV);
z = (float)DV - (float)random(2 * DV);
MakePosMatrix(&sp->dpos, x, y, z);
MakeRotMatrix(&sp->rot, 0.0f, 0.0f, 0.0f);
sp->xrv = (float)DR - (float)random(2 * DR);
sp->yrv = (float)DR - (float)random(2 * DR);
sp->zrv = (float)DR - (float)random(2 * DR);
MakeRotMatrix(&sp->drot, sp->xrv, sp->yrv, sp->zrv);
}
}
void UpdateSphere(Sphere *sp)
{
GLboolean newRot;
if (fBounce)
{
newRot = GL_FALSE;
if (sp->pos.matrix[3][0] > DMINUSR || sp->pos.matrix[3][0] < -DMINUSR)
{
sp->dpos.matrix[3][0] = -sp->dpos.matrix[3][0];
sp->zrv = -sp->zrv;
sp->yrv = -sp->yrv;
newRot = GL_TRUE;
}
if (sp->pos.matrix[3][1] > DMINUSR || sp->pos.matrix[3][1] < -DMINUSR)
{
sp->dpos.matrix[3][1] = -sp->dpos.matrix[3][1];
sp->zrv = -sp->zrv;
sp->xrv = -sp->xrv;
newRot = GL_TRUE;
}
if (sp->pos.matrix[3][2] > DEPTH || sp->pos.matrix[3][2] < -DEPTH)
{
sp->dpos.matrix[3][2] = -sp->dpos.matrix[3][2];
sp->xrv = -sp->xrv;
sp->yrv = -sp->yrv;
newRot = GL_TRUE;
}
if (newRot)
{
MakeRotMatrix(&sp->drot, sp->xrv, sp->yrv, sp->zrv);
}
__glMultMatrix(&sp->pos, &sp->dpos, &sp->pos);
}
if (fRotate)
{
__glMultMatrix(&sp->rot, &sp->drot, &sp->rot);
}
}
#define TAN_60 1.732
void SetTriangleVertices(LPD3DVERTEX v, float z, UINT ww, UINT wh, float a,
int ox, int oy)
{
float dx, dy;
float b = (float)sqrt((4 * a) / TAN_60);
float h = (2 * a) / b;
float x = (float)((b / 2) * (TAN_60 / 2));
float cx, cy;
dx = (float)ww;
dy = (float)wh;
cx = dx / 2 + ox;
cy = dy / 2 + oy;
/* V 0 */
v[0].x = cx;
v[0].y = cy + (h - x);
v[0].z = z;
v[0].color = RGB_MAKE(255, 0, 0);
v[0].tu = D3DVAL(0.5);
v[0].tv = D3DVAL(0.0);
/* V 1 */
v[1].x = cx + (b / 2);
v[1].y = cy - x;
v[1].z = z;
v[1].color = RGB_MAKE(255, 255, 255);
v[1].tu = D3DVAL(1.0);
v[1].tv = D3DVAL(1.0);
/* V 2 */
v[2].x = cx - (b / 2);
v[2].y = cy - x;
v[2].z = z;
v[2].color = RGB_MAKE(255, 255, 0);
v[2].tu = D3DVAL(0.0);
v[2].tv = D3DVAL(1.0);
}
void InitFill(LPD3DVERTEX *ppVertices, LPD3DTRIANGLE *ppTriangles)
{
*ppVertices = (LPD3DVERTEX)Malloc(3 * FILL_TRIANGLES * sizeof(D3DVERTEX));
*ppTriangles = (LPD3DTRIANGLE)Malloc(FILL_TRIANGLES * sizeof(D3DTRIANGLE));
}
D3DVERTEX *pPolyVertices;
D3DTRIANGLE *pPolyTriangles;
int nNumVertices, nNumFaces;
int *pPolyStrip;
int nStripIndices;
D3DVERTEX *pFillVertices;
D3DTRIANGLE *pFillTriangles;
int *pIndices;
int nIndices;
int nTriangles;
#define POLYMODE_POINT 0
#define POLYMODE_LINE 1
#define POLYMODE_FILL 2
#define POLYMODE_COUNT 3
GLenum ePolygonModes[] =
{
GL_POINT, GL_LINE, GL_FILL
};
int iPolygonMode = POLYMODE_FILL;
#define SMODEL_SMOOTH 0
#define SMODEL_FLAT 1
#define SMODEL_COUNT 2
GLenum eShadeModels[] =
{
GL_SMOOTH, GL_FLAT
};
char *pszShadeModels[] =
{
"smooth", "flat"
};
int iShadeModel = SMODEL_SMOOTH;
#define PRIM_TRIANGLES 0
#define PRIM_TSTRIP 1
#define PRIM_QSTRIP 2
#define PRIM_COUNT 3
GLenum ePrimTypes[] =
{
GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_QUAD_STRIP
};
char *pszPrimTypes[] =
{
"Tris",
"TStrip",
"QStrip"
};
int iPrimType = PRIM_TRIANGLES;
int total_ms = 0;
int total_tris = 0 ;
double peak_tri = 0, peak_fill = 0, avg_tri = 0, avg_fill = 0;
int avg_cnt = 0;
void ModeChange(void)
{
total_ms = 0;
total_tris = 0;
avg_tri = 0;
avg_fill = 0;
avg_cnt = 0;
}
void SetPrim(int iNew)
{
ModeChange();
iPrimType = iNew;
switch(iTest)
{
case TEST_POLYS:
switch(iPrimType)
{
case PRIM_TRIANGLES:
pIndices = (int *)pPolyTriangles;
nIndices = nNumFaces*3;
nTriangles = nNumFaces;
break;
case PRIM_TSTRIP:
case PRIM_QSTRIP:
pIndices = pPolyStrip;
nIndices = nStripIndices;
nTriangles = nSections*2;
break;
}
nTriangles *= NSPHERES;
break;
case TEST_FILL:
pIndices = (int *)pFillTriangles;
nIndices = FILL_TRIANGLES*3;
nTriangles = FILL_TRIANGLES;
break;
}
}
void SetVertexArrayVertices(LPD3DVERTEX pVertices)
{
glVertexPointer(3, GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].x);
glNormalPointer(GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].nx);
glTexCoordPointer(2, GL_FLOAT, sizeof(D3DVERTEX), &pVertices[0].tu);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(D3DVERTEX),
&pVertices[0].color);
}
void SetFill(int iNewSize, int iNewOrder)
{
int i;
float z;
int NumTri;
LPD3DVERTEX pVert;
LPD3DTRIANGLE pTri;
UINT w, h;
float area;
int ox, oy, dox, doy;
RECT rct;
ModeChange();
iFillSize = iNewSize;
iOrder = iNewOrder;
switch(iFillSize)
{
case AREA_LARGE:
iTriangleArea = LARGE_AREA;
iSwapWidth = LAWIDTH;
iSwapHeight = LAHEIGHT;
break;
case AREA_MEDIUM:
iTriangleArea = MEDIUM_AREA;
iSwapWidth = MAWIDTH;
iSwapHeight = MAHEIGHT;
break;
}
glScissor((WIDTH-iSwapWidth)/2, (HEIGHT-iSwapHeight)/2,
iSwapWidth, iSwapHeight);
w = WIDTH;
h = HEIGHT;
NumTri = FILL_TRIANGLES;
pVert = pFillVertices;
if (fSpread)
{
ox = -NumTri*2;
oy = -NumTri*2;
dox = 4;
doy = 4;
}
else
{
ox = 0;
oy = 0;
dox = 0;
doy = 0;
}
if (iOrder == FRONT_TO_BACK)
{
for (i = 0, z = (float)0.0; i < NumTri; i++, z -= (float)0.9 / NumTri)
{
SetTriangleVertices(pVert, z, w, h, (float)iTriangleArea,
ox, oy);
pVert += 3;
ox += dox;
oy += doy;
}
}
else
{
for (i = 0, z = (float)-0.9; i < NumTri; i++, z += (float)0.9 / NumTri)
{
SetTriangleVertices(pVert, z, w, h, (float)iTriangleArea,
ox, oy);
pVert += 3;
ox += dox;
oy += doy;
}
}
pTri = pFillTriangles;
for (i = 0; i < NumTri; i++)
{
pTri->v1 = i*3;
pTri->v2 = i*3+1;
pTri->v3 = i*3+2;
pTri++;
}
GetClientRect(auxGetHWND(), &rct);
FillRect(auxGetHDC(), &rct, GetStockObject(BLACK_BRUSH));
}
static __GLmatrix proj = {
D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(2.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(1.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(-1.0), D3DVAL(0.0)
};
static __GLmatrix view = {
D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(1.0), D3DVAL(0.0),
D3DVAL(0.0), D3DVAL(0.0), D3DVAL(7.0), D3DVAL(1.0)
};
void SetTest(int iNew)
{
RECT rct;
ModeChange();
iTest = iNew;
switch(iTest)
{
case TEST_POLYS:
glDisableClientState(GL_COLOR_ARRAY);
glEnable(GL_LIGHTING);
glEnable(GL_CULL_FACE);
iTexMode = TEXMODE_REPLACE;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#if 0
gluPerspective(45, 1, .01, 15);
gluLookAt(0, 0, 8, 0, 0, 0, 0, 1, 0);
#else
glLoadMatrixf((float *)&proj);
glMultMatrixf((float *)&view);
glDepthRange(1, 0);
#endif
glMatrixMode(GL_MODELVIEW);
SetVertexArrayVertices(pPolyVertices);
iSwapWidth = SPWIDTH;
iSwapHeight = SPHEIGHT;
glScissor((WIDTH-iSwapWidth)/2, (HEIGHT-iSwapHeight)/2,
iSwapWidth, iSwapHeight);
break;
case TEST_FILL:
glEnableClientState(GL_COLOR_ARRAY);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
iTexMode = TEXMODE_MODULATE;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, 0, HEIGHT, 0.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
SetVertexArrayVertices(pFillVertices);
SetFill(iFillSize, iOrder);
break;
}
SetPrim(iPrimType);
GetClientRect(auxGetHWND(), &rct);
FillRect(auxGetHDC(), &rct, GetStockObject(BLACK_BRUSH));
}
void Init(void)
{
float fv4[4];
int iPrim, iOldPrim;
if (!GenerateSphere(SRADIUS, nRings, nSections, 1.0f, 1.0f, 1.0f,
&pPolyVertices, &pPolyTriangles,
&nNumVertices, &nNumFaces))
{
printf("Unable to generate sphere data\n");
exit(1);
}
nStripIndices = CreateStrip(nSections, &pPolyStrip);
InitSpheres();
InitFill(&pFillVertices, &pFillTriangles);
fv4[0] = 0.05f;
fv4[1] = 0.05f;
fv4[2] = 0.05f;
fv4[3] = 1.0f;
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, fv4);
fv4[0] = 0.0f;
fv4[1] = 1.0f;
fv4[2] = 1.0f;
fv4[3] = 0.0f;
glLightfv(GL_LIGHT0, GL_POSITION, fv4);
fv4[0] = 0.9f;
fv4[1] = 0.9f;
fv4[2] = 0.9f;
fv4[3] = 1.0f;
glLightfv(GL_LIGHT0, GL_DIFFUSE, fv4);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if (!fSingleColor)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
}
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
#ifdef TEXOBJ
glGenTextures(1, &uiTexObj);
glBindTexture(GL_TEXTURE_2D, uiTexObj);
#endif
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(GL_TEXTURE_2D, 0, 3, pTexture->sizeX, pTexture->sizeY, 0,
GL_RGB, GL_UNSIGNED_BYTE, pTexture->data);
glEnable(GL_TEXTURE_2D);
glDisable(GL_DITHER);
#ifdef GL_EXT_clip_volume
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST);
#endif
SetTest(iTest);
glClear(GL_COLOR_BUFFER_BIT);
if (fDisplayList)
{
iDlist = glGenLists(3);
iOldPrim = iPrimType;
for (iPrim = 0; iPrim < PRIM_COUNT; iPrim++)
{
SetPrim(iPrim);
glNewList(iDlist+iPrim, GL_COMPILE);
glDrawElements(ePrimTypes[iPrim], nIndices,
GL_UNSIGNED_INT, pIndices);
glEndList();
}
SetPrim(iOldPrim);
}
}
void Redraw(void)
{
DWORD ms;
int i;
Sphere *sp;
float fv4[4];
int iv1[1];
int loop;
__GLmatrix xform;
ms = GetTickCount();
for (loop = 0; loop < iMultiLoop; loop++)
{
#if PROFILE
if (loop > 0)
{
StartCAP();
}
#endif
if (fUseScissor)
{
glEnable(GL_SCISSOR_TEST);
if (glAddSwapHintRectWIN != NULL)
{
glAddSwapHintRectWIN((WIDTH-iSwapWidth)/2,
(HEIGHT-iSwapHeight)/2,
iSwapWidth, iSwapHeight);
}
}
if (glIsEnabled(GL_DEPTH_TEST))
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
else
{
glClear(GL_COLOR_BUFFER_BIT);
}
if (fUseScissor)
{
glDisable(GL_SCISSOR_TEST);
}
if (fSingleColor && iTest == TEST_POLYS)
{
fv4[0] = 1.0f;
fv4[1] = 1.0f;
fv4[2] = 1.0f;
fv4[3] = 1.0f;
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fv4);
}
fv4[0] = 0.6f;
fv4[1] = 0.6f;
fv4[2] = 0.6f;
fv4[3] = 1.0f;
glMaterialfv(GL_FRONT, GL_SPECULAR, fv4);
iv1[0] = 40;
glMaterialiv(GL_FRONT, GL_SHININESS, iv1);
switch(iTest)
{
case TEST_POLYS:
sp = &spheres[0];
for (i = 0; i < NSPHERES; i++)
{
UpdateSphere(sp);
// Always done to even out timings
#if 1
__glMultMatrix(&xform, &sp->rot, &sp->pos);
#else
__glMultMatrix(&xform, &sp->pos, &sp->rot);
#endif
if (fBounce && fRotate)
{
glLoadMatrixf(&xform.matrix[0][0]);
}
else if (fRotate)
{
glLoadMatrixf(&sp->rot.matrix[0][0]);
}
else
{
glLoadMatrixf(&sp->pos.matrix[0][0]);
}
#if 1
glVertexPointer(3, GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].x);
glNormalPointer(GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].nx);
glTexCoordPointer(2, GL_FLOAT, sizeof(D3DVERTEX), &pPolyVertices[0].tu);
fv4[0] = 1.0f;
fv4[1] = 1.0f;
fv4[2] = 1.0f;
fv4[3] = 1.0f;
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, fv4);
fv4[0] = 0.6f;
fv4[1] = 0.6f;
fv4[2] = 0.6f;
fv4[3] = 1.0f;
glMaterialfv(GL_FRONT, GL_SPECULAR, fv4);
iv1[0] = 40;
glMaterialiv(GL_FRONT, GL_SHININESS, iv1);
glBindTexture(GL_TEXTURE_2D, uiTexObj);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glEnable(GL_TEXTURE_2D);
glDepthRange(1, 0);
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glEnable(GL_LIGHTING);
#endif
if (fDisplayList)
{
glCallList(iDlist+iPrimType);
}
else
{
glDrawElements(ePrimTypes[iPrimType], nIndices,
GL_UNSIGNED_INT, pIndices);
}
sp++;
}
break;
case TEST_FILL:
glDrawElements(GL_TRIANGLES, nIndices, GL_UNSIGNED_INT, pIndices);
break;
}
if (fSwap && !fSingle)
{
auxSwapBuffers();
}
else
{
glFinish();
}
}
#ifdef PROFILE
if (iMultiLoop > 1)
{
StopCAP();
}
#endif
ms = GetTickCount()-ms;
total_ms += ms;
total_tris += nTriangles*iMultiLoop;
if (total_ms > 2000)
{
double val;
switch(iTest)
{
case TEST_POLYS:
val = (double)total_tris*1000.0/total_ms;
if (val > peak_tri)
{
peak_tri = val;
}
avg_tri += val;
break;
case TEST_FILL:
val = (double)iTriangleArea*total_tris*1000.0/total_ms;
if (val > peak_fill)
{
peak_fill = val;
}
avg_fill += val;
break;
}
avg_cnt++;
if (fVerbose)
{
printf("%s, %s", pszPrimTypes[iPrimType],
pszShadeModels[iShadeModel]);
if (glIsEnabled(GL_CULL_FACE))
{
printf(", cull");
}
if (glIsEnabled(GL_LIGHTING))
{
printf(", lit");
}
if (glIsEnabled(GL_TEXTURE_2D))
{
printf(", %s", pszTexModes[iTexMode]);
}
if (glIsEnabled(GL_DITHER))
{
printf(", dither");
}
if (glIsEnabled(GL_DEPTH_TEST))
{
printf(", z");
}
#ifdef GL_EXT_clip_volume
glGetIntegerv(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, &iv1[0]);
if (iv1[0] != GL_FASTEST)
#endif
{
printf(", clip");
}
if (fSwap)
{
printf(", swap");
}
if (fRotate)
{
printf(", rotate");
}
if (fBounce)
{
printf(", bounce");
}
if (fPerspective)
{
printf(", persp");
}
printf(", %d tri/frame\n", nTriangles);
switch(iTest)
{
case TEST_POLYS:
printf("%d ms, %d tri, %.3lf tri/sec, %.3lf peak, %.3lf avg\n",
total_ms, total_tris, val, peak_tri,
avg_tri/avg_cnt);
break;
case TEST_FILL:
printf("%d ms, %s, area %d, %.3lf pix/sec, "
"%.3lf peak, %.3lf avg\n",
total_ms, pszOrders[iOrder], iTriangleArea,
val, peak_fill, avg_fill/avg_cnt);
break;
}
}
else
{
char msg[80];
switch(iTest)
{
case TEST_POLYS:
sprintf(msg, "%.3lf tri/sec, %.3lf peak, %.3lf avg",
val, peak_tri, avg_tri/avg_cnt);
break;
case TEST_FILL:
sprintf(msg, "%.3lf pix/sec, %.3lf peak, %.3lf avg",
val, peak_fill, avg_fill/avg_cnt);
break;
}
SetWindowText(auxGetHWND(), msg);
}
total_ms = 0;
total_tris = 0;
}
}
void Reshape(GLsizei w, GLsizei h)
{
glViewport(0, 0, w, h);
}
void Step(void)
{
Redraw();
}
void KeyB(void)
{
ModeChange();
fBounce = !fBounce;
}
void Keyc(void)
{
ModeChange();
if (glIsEnabled(GL_CULL_FACE))
{
glDisable(GL_CULL_FACE);
}
else
{
glEnable(GL_CULL_FACE);
}
}
void KeyC(void)
{
ModeChange();
fUseScissor = !fUseScissor;
}
void Keyh(void)
{
ModeChange();
if (glIsEnabled(GL_DITHER))
{
glDisable(GL_DITHER);
}
else
{
glEnable(GL_DITHER);
}
}
void Keyi(void)
{
iFillSize = (iFillSize+1) % AREA_COUNT;
SetFill(iFillSize, iOrder);
}
void Keyl(void)
{
ModeChange();
if (glIsEnabled(GL_LIGHTING))
{
glDisable(GL_LIGHTING);
}
else
{
glEnable(GL_LIGHTING);
}
}
void Keym(void)
{
ModeChange();
iPolygonMode = (iPolygonMode+1) % POLYMODE_COUNT;
glPolygonMode(GL_FRONT_AND_BACK, ePolygonModes[iPolygonMode]);
}
void Keyo(void)
{
iOrder = (iOrder+1) % ORDER_COUNT;
SetFill(iFillSize, iOrder);
}
void Keyp(void)
{
ModeChange();
fPerspective = !fPerspective;
glHint(GL_PERSPECTIVE_CORRECTION_HINT,
fPerspective ? GL_NICEST : GL_FASTEST);
}
void KeyP(void)
{
#ifdef GL_EXT_clip_volume
int iv1[1];
ModeChange();
glGetIntegerv(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, &iv1[0]);
if (iv1[0] == GL_FASTEST)
{
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_DONT_CARE);
}
else
{
glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST);
}
#endif
}
void KeyR(void)
{
ModeChange();
fRotate = !fRotate;
}
void Keys(void)
{
ModeChange();
iShadeModel = (iShadeModel+1) % SMODEL_COUNT;
glShadeModel(eShadeModels[iShadeModel]);
}
void KeyS(void)
{
fSpread = !fSpread;
SetFill(iFillSize, iOrder);
}
void Keyt(void)
{
SetPrim((iPrimType+1) % PRIM_COUNT);
}
void KeyT(void)
{
iTest = (iTest+1) % TEST_COUNT;
SetTest(iTest);
}
void Keyw(void)
{
ModeChange();
fSwap = !fSwap;
}
void Keyx(void)
{
ModeChange();
if (glIsEnabled(GL_TEXTURE_2D))
{
glDisable(GL_TEXTURE_2D);
}
else
{
glEnable(GL_TEXTURE_2D);
}
}
void KeyX(void)
{
ModeChange();
iTexMode = (iTexMode+1) % TEXMODE_COUNT;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, eTexModes[iTexMode]);
}
void Keyz(void)
{
ModeChange();
if (glIsEnabled(GL_DEPTH_TEST))
{
glDisable(GL_DEPTH_TEST);
}
else
{
glEnable(GL_DEPTH_TEST);
}
}
void KeySPACE(void)
{
fPaused = !fPaused;
if (fPaused)
{
auxIdleFunc(NULL);
}
else
{
auxIdleFunc(Step);
}
}
void __cdecl main(int argc, char **argv)
{
int mode;
int wd, ht;
char szWinDir[256];
int l;
wd = WIDTH;
ht = HEIGHT;
while (--argc > 0)
{
argv++;
if (!strcmp(*argv, "-sb"))
{
fSingle = TRUE;
}
else if (!strcmp(*argv, "-paused"))
{
fPaused = TRUE;
}
else if (!strcmp(*argv, "-exit"))
{
fExit = TRUE;
}
else if (!strcmp(*argv, "-cols"))
{
fSingleColor = FALSE;
}
else if (!strcmp(*argv, "-v"))
{
fVerbose = TRUE;
}
else if (!strcmp(*argv, "-nodlist"))
{
fDisplayList = FALSE;
}
else if (!strcmp(*argv, "-norotate"))
{
fRotate = FALSE;
}
else if (!strcmp(*argv, "-nobounce"))
{
fBounce = FALSE;
}
else if (!strcmp(*argv, "-noscissor"))
{
fUseScissor = FALSE;
}
else if (!strncmp(*argv, "-multi", 6))
{
sscanf(*argv+6, "%d", &iMultiLoop);
}
else if (!strncmp(*argv, "-wd", 3))
{
sscanf(*argv+3, "%d", &wd);
}
else if (!strncmp(*argv, "-ht", 3))
{
sscanf(*argv+3, "%d", &ht);
}
else if (!strncmp(*argv, "-rings", 6))
{
sscanf(*argv+6, "%d", &nRings);
}
else if (!strncmp(*argv, "-sections", 9))
{
sscanf(*argv+9, "%d", &nSections);
}
else if (!strncmp(*argv, "-tst", 4))
{
sscanf(*argv+4, "%d", &iTest);
}
else if (!strncmp(*argv, "-fsz", 4))
{
sscanf(*argv+4, "%d", &iFillSize);
}
}
auxInitPosition(10, 10, wd, ht);
mode = AUX_RGB | AUX_DEPTH16;
if (!fSingle)
{
mode |= AUX_DOUBLE;
}
auxInitDisplayMode(mode);
auxInitWindow("DrawElements Performance Test");
auxReshapeFunc(Reshape);
if (!fPaused)
{
auxIdleFunc(Step);
}
l = GetWindowsDirectory(szWinDir, sizeof(szWinDir));
if (l == 0)
{
printf("Unable to get windows directory\n");
exit(1);
}
strcpy(szWinDir+l, "\\cover8.bmp");
pTexture = auxDIBImageLoad(szWinDir);
if (pTexture == NULL)
{
printf("Unable to load texture\n");
exit(1);
}
auxKeyFunc(AUX_B, KeyB);
auxKeyFunc(AUX_c, Keyc);
auxKeyFunc(AUX_C, KeyC);
auxKeyFunc(AUX_h, Keyh);
auxKeyFunc(AUX_i, Keyi);
auxKeyFunc(AUX_l, Keyl);
auxKeyFunc(AUX_m, Keym);
auxKeyFunc(AUX_o, Keyo);
auxKeyFunc(AUX_p, Keyp);
auxKeyFunc(AUX_P, KeyP);
auxKeyFunc(AUX_R, KeyR);
auxKeyFunc(AUX_s, Keys);
auxKeyFunc(AUX_S, KeyS);
auxKeyFunc(AUX_t, Keyt);
auxKeyFunc(AUX_T, KeyT);
auxKeyFunc(AUX_w, Keyw);
auxKeyFunc(AUX_x, Keyx);
auxKeyFunc(AUX_X, KeyX);
auxKeyFunc(AUX_z, Keyz);
auxKeyFunc(AUX_SPACE, KeySPACE);
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
glAddSwapHintRectWIN = (PFNGLADDSWAPHINTRECTWINPROC)
wglGetProcAddress("glAddSwapHintRectWIN");
#if 0
_controlfp((unsigned int)
(~(_EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW)), _MCW_EM);
#endif
Init();
if (fExit)
{
Redraw();
}
else
{
auxMainLoop(Redraw);
}
}