132001f49Smrg/*
232001f49Smrg * Copyright © 2010 Pauli Nieminen
332001f49Smrg *
432001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
532001f49Smrg * copy of this software and associated documentation files (the "Software"),
632001f49Smrg * to deal in the Software without restriction, including without limitation
732001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
832001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
932001f49Smrg * Software is furnished to do so, subject to the following conditions:
1032001f49Smrg *
1132001f49Smrg * The above copyright notice and this permission notice (including the next
1232001f49Smrg * paragraph) shall be included in all copies or substantial portions of the
1332001f49Smrg * Software.
1432001f49Smrg *
1532001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1632001f49Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1732001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1832001f49Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1932001f49Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2032001f49Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2132001f49Smrg * DEALINGS IN THE SOFTWARE.
2232001f49Smrg */
2332001f49Smrg
2432001f49Smrg
2532001f49Smrg/*
2632001f49Smrg * Test case for huge cva arrays. Mesa code has to split this to multiple VBOs
2732001f49Smrg * which had memory access error.
2832001f49Smrg * This test case doesn't render incorrectly but valgrind showed the memory
2932001f49Smrg * access error.
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg#include <stdlib.h>
3332001f49Smrg#include <stdio.h>
3432001f49Smrg#include <string.h>
3532001f49Smrg#include <stddef.h>	/* for ptrdiff_t, referenced by GL.h when GL_GLEXT_LEGACY defined */
3632001f49Smrg#ifdef _WIN32
3732001f49Smrg#include <windows.h>
3832001f49Smrg#endif
3932001f49Smrg#define GL_GLEXT_LEGACY
4032001f49Smrg#include "glut_wrap.h"
4132001f49Smrg
4232001f49SmrgGLfloat *verts;
4332001f49Smrg
4432001f49SmrgGLubyte *color;
4532001f49Smrg
4632001f49SmrgGLuint *indices;
4732001f49Smrg
4832001f49Smrg#define rows 1000 /* Create 1000x1000 vertex grid */
4932001f49Smrg#define row_width 5000.0
5032001f49Smrg#define grid_depth -50.0
5132001f49SmrgGLuint nr_verts_in_row = rows;
5232001f49SmrgGLuint nr_indices_in_strip = rows * 2;
5332001f49Smrg
5432001f49SmrgGLboolean double_buffer;
5532001f49SmrgGLboolean compiled = GL_TRUE;
5632001f49Smrg
5732001f49Smrgstatic void generate_verts( void )
5832001f49Smrg{
5932001f49Smrg	unsigned x, y;
6032001f49Smrg	GLfloat step = row_width /(GLfloat)(nr_verts_in_row - 1);
6132001f49Smrg	verts = malloc(sizeof(verts[0]) * 4 * nr_verts_in_row * nr_verts_in_row);
6232001f49Smrg
6332001f49Smrg	for (y = 0; y < nr_verts_in_row; ++y) {
6432001f49Smrg		for (x = 0; x < nr_verts_in_row; ++x) {
6532001f49Smrg			unsigned idx = 4*(x + y * nr_verts_in_row);
6632001f49Smrg			verts[idx + 0] = step * x - row_width/2.0;
6732001f49Smrg			verts[idx + 1] = step * y - row_width/2.0;
6832001f49Smrg			/* deep enough not to be vissible */
6932001f49Smrg			verts[idx + 2] = grid_depth;
7032001f49Smrg			verts[idx + 3] = 0.0;
7132001f49Smrg		}
7232001f49Smrg	}
7332001f49Smrg	glVertexPointer( 3, GL_FLOAT, sizeof(verts[0])*4, verts );
7432001f49Smrg}
7532001f49Smrg
7632001f49Smrgstatic void generate_colors( void )
7732001f49Smrg{
7832001f49Smrg	unsigned x, y;
7932001f49Smrg	GLfloat step = 255.0/(GLfloat)(nr_verts_in_row - 1);
8032001f49Smrg	color = malloc(sizeof(color[0]) * 4 * nr_verts_in_row *	nr_verts_in_row);
8132001f49Smrg
8232001f49Smrg	for (y = 0; y < nr_verts_in_row; ++y) {
8332001f49Smrg		for (x = 0; x < nr_verts_in_row; ++x) {
8432001f49Smrg			unsigned idx = 4*(x + y * nr_verts_in_row);
8532001f49Smrg			color[idx + 0] = (GLubyte)(step * x);
8632001f49Smrg			color[idx + 1] = 0x00;
8732001f49Smrg			color[idx + 2] = (GLubyte)(step * y);
8832001f49Smrg			color[idx + 3] = 0x00;
8932001f49Smrg		}
9032001f49Smrg	}
9132001f49Smrg	glColorPointer( 4, GL_UNSIGNED_BYTE, 0, color );
9232001f49Smrg}
9332001f49Smrg
9432001f49Smrgstatic void generate_indices( void )
9532001f49Smrg{
9632001f49Smrg	unsigned strip, i;
9732001f49Smrg
9832001f49Smrg	/* indice size * number of strips * number of indices in strip */
9932001f49Smrg	indices = malloc(sizeof(indices[0]) * (nr_verts_in_row - 1) *
10032001f49Smrg			(nr_indices_in_strip));
10132001f49Smrg
10232001f49Smrg	for (strip = 0; strip < nr_verts_in_row - 1; strip += 2) {
10332001f49Smrg		for (i = 0; i < nr_indices_in_strip; i+=2) {
10432001f49Smrg			unsigned idx = i + strip * nr_indices_in_strip;
10532001f49Smrg			unsigned idx2 = (nr_indices_in_strip - i - 2) + (strip +
10632001f49Smrg					1) * (nr_indices_in_strip);
10732001f49Smrg			indices[idx + 1] = i/2 + strip*nr_verts_in_row;
10832001f49Smrg			indices[idx] = i/2 + (strip + 1)*nr_verts_in_row;
10932001f49Smrg			if (strip + 1 < nr_verts_in_row - 1) {
11032001f49Smrg				indices[idx2] = i/2 + (strip + 1)*nr_verts_in_row;
11132001f49Smrg				indices[idx2 + 1] = i/2 + (strip + 2)*nr_verts_in_row;
11232001f49Smrg			}
11332001f49Smrg		}
11432001f49Smrg	}
11532001f49Smrg}
11632001f49Smrg
11732001f49Smrgstatic void init( void )
11832001f49Smrg{
11932001f49Smrg
12032001f49Smrg
12132001f49Smrg	generate_verts();
12232001f49Smrg	generate_colors();
12332001f49Smrg	generate_indices();
12432001f49Smrg
12532001f49Smrg	glClearColor( 0.0, 0.0, 0.0, 0.0 );
12632001f49Smrg	glShadeModel( GL_SMOOTH );
12732001f49Smrg
12832001f49Smrg	glEnableClientState( GL_VERTEX_ARRAY );
12932001f49Smrg	glEnableClientState( GL_COLOR_ARRAY );
13032001f49Smrg
13132001f49Smrg	glMatrixMode( GL_PROJECTION );
13232001f49Smrg	glLoadIdentity();
13332001f49Smrg	glFrustum( -100.0, 100.0, -100.0, 100.0, 1.0, 100.0 );
13432001f49Smrg	glMatrixMode( GL_MODELVIEW );
13532001f49Smrg	glLoadIdentity();
13632001f49Smrg
13732001f49Smrg#ifdef GL_EXT_compiled_vertex_array
13832001f49Smrg	if ( compiled ) {
13932001f49Smrg		glLockArraysEXT( 0, rows * rows );
14032001f49Smrg	}
14132001f49Smrg#endif
14232001f49Smrg}
14332001f49Smrg
14432001f49Smrgstatic void display( void )
14532001f49Smrg{
14632001f49Smrg	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
14732001f49Smrg
14832001f49Smrg	glDrawElements( GL_TRIANGLE_STRIP, nr_indices_in_strip * (nr_verts_in_row - 1) , GL_UNSIGNED_INT, indices );
14932001f49Smrg
15032001f49Smrg	if ( double_buffer )
15132001f49Smrg		glutSwapBuffers();
15232001f49Smrg	else
15332001f49Smrg		glFlush();
15432001f49Smrg}
15532001f49Smrg
15632001f49Smrgstatic void keyboard( unsigned char key, int x, int y )
15732001f49Smrg{
15832001f49Smrg	switch ( key ) {
15932001f49Smrg	case 27:
16032001f49Smrg		exit( 0 );
16132001f49Smrg		break;
16232001f49Smrg	}
16332001f49Smrg
16432001f49Smrg	glutPostRedisplay();
16532001f49Smrg}
16632001f49Smrg
16732001f49Smrgstatic GLboolean args( int argc, char **argv )
16832001f49Smrg{
16932001f49Smrg    GLint i;
17032001f49Smrg
17132001f49Smrg    double_buffer = GL_TRUE;
17232001f49Smrg
17332001f49Smrg    for ( i = 1 ; i < argc ; i++ ) {
17432001f49Smrg	if ( strcmp( argv[i], "-sb" ) == 0 ) {
17532001f49Smrg	    double_buffer = GL_FALSE;
17632001f49Smrg	} else if ( strcmp( argv[i], "-db" ) == 0 ) {
17732001f49Smrg	    double_buffer = GL_TRUE;
17832001f49Smrg	} else {
17932001f49Smrg	    fprintf( stderr, "%s (Bad option).\n", argv[i] );
18032001f49Smrg	    return GL_FALSE;
18132001f49Smrg	}
18232001f49Smrg    }
18332001f49Smrg    return GL_TRUE;
18432001f49Smrg}
18532001f49Smrg
18632001f49Smrgint main( int argc, char **argv )
18732001f49Smrg{
18832001f49Smrg   GLenum type;
18932001f49Smrg   char *string;
19032001f49Smrg   double version;
19132001f49Smrg
19232001f49Smrg   glutInit( &argc, argv );
19332001f49Smrg
19432001f49Smrg   if ( args( argc, argv ) == GL_FALSE ) {
19532001f49Smrg      exit( 1 );
19632001f49Smrg   }
19732001f49Smrg
19832001f49Smrg   type = GLUT_RGB | GLUT_DEPTH;
19932001f49Smrg   type |= ( double_buffer ) ? GLUT_DOUBLE : GLUT_SINGLE;
20032001f49Smrg
20132001f49Smrg   glutInitDisplayMode( type );
20232001f49Smrg   glutInitWindowSize( 250, 250 );
20332001f49Smrg   glutInitWindowPosition( 100, 100 );
20432001f49Smrg   glutCreateWindow( "CVA Test" );
20532001f49Smrg
20632001f49Smrg   /* Make sure the server supports GL 1.2 vertex arrays.
20732001f49Smrg    */
20832001f49Smrg   string = (char *) glGetString( GL_VERSION );
20932001f49Smrg
21032001f49Smrg   version = atof(string);
21132001f49Smrg   if ( version < 1.2 ) {
21232001f49Smrg      fprintf( stderr, "This program requires OpenGL 1.2 vertex arrays.\n" );
21332001f49Smrg      exit( -1 );
21432001f49Smrg   }
21532001f49Smrg
21632001f49Smrg   /* See if the server supports compiled vertex arrays.
21732001f49Smrg    */
21832001f49Smrg   string = (char *) glGetString( GL_EXTENSIONS );
21932001f49Smrg
22032001f49Smrg   if ( !strstr( string, "GL_EXT_compiled_vertex_array" ) ) {
22132001f49Smrg      fprintf( stderr, "Compiled vertex arrays not supported by this renderer.\n" );
22232001f49Smrg      compiled = GL_FALSE;
22332001f49Smrg   }
22432001f49Smrg
22532001f49Smrg   init();
22632001f49Smrg
22732001f49Smrg   glutDisplayFunc( display );
22832001f49Smrg   glutKeyboardFunc( keyboard );
22932001f49Smrg   glutMainLoop();
23032001f49Smrg
23132001f49Smrg   return 0;
23232001f49Smrg}
233