2008-11-02 07:58:06 -07:00
|
|
|
/*
|
|
|
|
* Test glReadPixels speed
|
|
|
|
* Brian Paul
|
|
|
|
* 9 April 2004
|
|
|
|
*
|
|
|
|
* Compile:
|
|
|
|
* gcc readrate.c -L/usr/X11R6/lib -lglut -lGLU -lGL -lX11 -o readrate
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
2010-05-22 14:05:42 -06:00
|
|
|
#include <GL/glew.h>
|
2008-11-02 07:58:06 -07:00
|
|
|
#include <GL/glut.h>
|
|
|
|
|
|
|
|
/* Hack, to test drawing instead of reading */
|
|
|
|
#define DRAW 0
|
|
|
|
|
|
|
|
#define MAX_WIDTH 1280
|
|
|
|
#define MAX_HEIGHT 1024
|
|
|
|
|
|
|
|
#define NUM_WIDTHS 4
|
|
|
|
#define NUM_HEIGHTS 4
|
|
|
|
static const GLint Widths[] = {256, 512, 1024, 1280};
|
|
|
|
static const GLint Heights[] = {4, 32, 256, 512, 768, 1024};
|
|
|
|
static int WidthIndex = 1, HeightIndex = 3;
|
|
|
|
static GLubyte *Buffer = NULL;
|
|
|
|
static GLboolean Benchmark = GL_TRUE;
|
|
|
|
|
|
|
|
#define NUM_PBO 2
|
|
|
|
|
|
|
|
static GLuint PBObjects[4];
|
|
|
|
|
|
|
|
static GLboolean HavePBO = GL_FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
struct format_type {
|
|
|
|
const char *Name;
|
|
|
|
GLuint Bytes;
|
|
|
|
GLenum Format;
|
|
|
|
GLenum Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct format_type Formats[] = {
|
|
|
|
{ "GL_RGB, GLubyte", 3, GL_RGB, GL_UNSIGNED_BYTE },
|
|
|
|
{ "GL_BGR, GLubyte", 3, GL_BGR, GL_UNSIGNED_BYTE },
|
|
|
|
{ "GL_RGBA, GLubyte", 4, GL_RGBA, GL_UNSIGNED_BYTE },
|
|
|
|
{ "GL_BGRA, GLubyte", 4, GL_BGRA, GL_UNSIGNED_BYTE },
|
|
|
|
{ "GL_ABGR, GLubyte", 4, GL_ABGR_EXT, GL_UNSIGNED_BYTE },
|
|
|
|
{ "GL_RGBA, GLuint_8_8_8_8", 4, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8 },
|
|
|
|
{ "GL_BGRA, GLuint_8_8_8_8", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8 },
|
|
|
|
{ "GL_BGRA, GLuint_8_8_8_8_rev", 4, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV },
|
|
|
|
#ifdef GL_EXT_packed_depth_stencil
|
|
|
|
{ "GL_DEPTH_STENCIL_EXT, GLuint24+8", 4, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT },
|
|
|
|
#endif
|
|
|
|
{ "GL_DEPTH_COMPONENT, GLfloat", 4, GL_DEPTH_COMPONENT, GL_FLOAT },
|
|
|
|
{ "GL_DEPTH_COMPONENT, GLuint", 4, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define NUM_FORMATS (sizeof(Formats) / sizeof(struct format_type))
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
PrintString(const char *s)
|
|
|
|
{
|
|
|
|
while (*s) {
|
|
|
|
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
MeasureFormat(struct format_type *fmt, GLint width, GLint height, GLuint pbo)
|
|
|
|
{
|
|
|
|
double t0 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
|
|
|
|
double t1;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
for (j = 0; ; j++) {
|
|
|
|
|
|
|
|
glBegin(GL_POINTS);
|
|
|
|
glVertex2f(1,1);
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
#if DRAW
|
|
|
|
glWindowPos2iARB(0,0);
|
|
|
|
glDrawPixels(width, height,
|
|
|
|
fmt->Format, fmt->Type, Buffer);
|
|
|
|
glFinish();
|
|
|
|
#else
|
|
|
|
if (pbo) {
|
|
|
|
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[j % NUM_PBO]);
|
|
|
|
glReadPixels(0, 0, width, height,
|
|
|
|
fmt->Format, fmt->Type, 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
glReadPixels(0, 0, width, height,
|
|
|
|
fmt->Format, fmt->Type, Buffer);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
t1 = glutGet(GLUT_ELAPSED_TIME) * 0.001;
|
|
|
|
if (t1 - t0 > 2.0) {
|
|
|
|
GLdouble rate = width * height / (1024.0 * 1024.0) * j / (t1 - t0);
|
|
|
|
#if DRAW
|
|
|
|
printf("%-32s %.2f draws/sec %.2f MPixels/sec %.2f MBytes/sec\n",
|
|
|
|
fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
|
|
|
|
#else
|
|
|
|
printf("%-32s %.2f reads/sec %.2f MPixels/sec %.2f MBytes/sec\n",
|
|
|
|
fmt->Name, j / (t1-t0), rate, rate * fmt->Bytes);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == 0) {
|
|
|
|
/* check for error */
|
|
|
|
GLenum err = glGetError();
|
|
|
|
if (err) {
|
|
|
|
printf("GL Error 0x%x for %s\n", err, fmt->Name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
Draw(void)
|
|
|
|
{
|
|
|
|
char str[1000];
|
|
|
|
int width = Widths[WidthIndex];
|
|
|
|
int height = Heights[HeightIndex];
|
|
|
|
int y = MAX_HEIGHT - 50;
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
glWindowPos2iARB(10, y);
|
|
|
|
sprintf(str, "ReadPixels size: %d x %d", width, height);
|
|
|
|
PrintString(str);
|
|
|
|
y -= 14;
|
|
|
|
|
|
|
|
glWindowPos2iARB(10, y);
|
|
|
|
PrintString("Press up/down/left/right to change image size.");
|
|
|
|
y -= 14;
|
|
|
|
|
|
|
|
glWindowPos2iARB(10, y);
|
|
|
|
PrintString("Press 'b' to run benchmark test.");
|
|
|
|
y -= 14;
|
|
|
|
|
|
|
|
if (Benchmark) {
|
|
|
|
glWindowPos2iARB(10, y);
|
|
|
|
PrintString("Testing...");
|
|
|
|
}
|
|
|
|
|
|
|
|
glutSwapBuffers();
|
|
|
|
|
|
|
|
if (Benchmark) {
|
|
|
|
GLuint i, pbo;
|
|
|
|
#if DRAW
|
|
|
|
printf("Draw size: Width=%d Height=%d\n", width, height);
|
|
|
|
#else
|
|
|
|
printf("Read size: Width=%d Height=%d\n", width, height);
|
|
|
|
#endif
|
|
|
|
for (pbo = 0; pbo <= HavePBO; pbo++) {
|
|
|
|
printf("Pixel Buffer Object: %d\n", pbo);
|
|
|
|
|
|
|
|
if (pbo == 0) {
|
|
|
|
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_FORMATS; i++) {
|
|
|
|
MeasureFormat(Formats + i, width, height, pbo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Benchmark = GL_FALSE;
|
|
|
|
|
|
|
|
/* redraw window text */
|
|
|
|
glutPostRedisplay();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
Reshape(int width, int height)
|
|
|
|
{
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
glOrtho(-1, 1, -1, 1, -1, 1);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
Key(unsigned char key, int x, int y)
|
|
|
|
{
|
|
|
|
(void) x;
|
|
|
|
(void) y;
|
|
|
|
switch (key) {
|
|
|
|
case 'b':
|
|
|
|
Benchmark = 1;
|
|
|
|
break;
|
|
|
|
case 27:
|
|
|
|
exit(0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
glutPostRedisplay();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
SpecialKey(int key, int x, int y)
|
|
|
|
{
|
|
|
|
(void) x;
|
|
|
|
(void) y;
|
|
|
|
switch (key) {
|
|
|
|
case GLUT_KEY_UP:
|
|
|
|
if (HeightIndex + 1 < NUM_WIDTHS)
|
|
|
|
HeightIndex++;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_DOWN:
|
|
|
|
if (HeightIndex > 0)
|
|
|
|
HeightIndex--;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_LEFT:
|
|
|
|
if (WidthIndex > 0)
|
|
|
|
WidthIndex--;
|
|
|
|
break;
|
|
|
|
case GLUT_KEY_RIGHT:
|
|
|
|
if (WidthIndex + 1 < NUM_HEIGHTS)
|
|
|
|
WidthIndex++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
glutPostRedisplay();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
Init(void)
|
|
|
|
{
|
|
|
|
Buffer = malloc(MAX_WIDTH * MAX_HEIGHT * 4);
|
|
|
|
assert(Buffer);
|
|
|
|
#if DRAW
|
|
|
|
printf("glDrawPixels test report:\n");
|
|
|
|
#else
|
|
|
|
printf("glReadPixels test report:\n");
|
|
|
|
#endif
|
|
|
|
printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER));
|
|
|
|
printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION));
|
|
|
|
|
|
|
|
if (glutExtensionSupported("GL_ARB_pixel_buffer_object")) {
|
|
|
|
int i;
|
|
|
|
HavePBO = 1;
|
|
|
|
glGenBuffersARB(NUM_PBO, PBObjects);
|
|
|
|
for (i = 0; i < NUM_PBO; i++) {
|
|
|
|
glBindBufferARB(GL_PIXEL_PACK_BUFFER_EXT, PBObjects[i]);
|
|
|
|
glBufferDataARB(GL_PIXEL_PACK_BUFFER_EXT,
|
|
|
|
MAX_WIDTH * MAX_HEIGHT * 4, NULL, GL_STREAM_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
glutInit(&argc, argv);
|
|
|
|
glutInitWindowPosition(0, 0);
|
|
|
|
glutInitWindowSize(MAX_WIDTH, MAX_HEIGHT);
|
|
|
|
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);
|
|
|
|
glutCreateWindow(argv[0]);
|
2010-05-22 14:05:42 -06:00
|
|
|
glewInit();
|
2008-11-02 07:58:06 -07:00
|
|
|
glutReshapeFunc(Reshape);
|
|
|
|
glutKeyboardFunc(Key);
|
|
|
|
glutSpecialFunc(SpecialKey);
|
|
|
|
glutDisplayFunc(Draw);
|
|
|
|
Init();
|
|
|
|
glutMainLoop();
|
|
|
|
return 0;
|
|
|
|
}
|