interleave.c revision 32001f49
1/*
2 * (C) Copyright IBM Corporation 2005
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file interleave.c
27 *
28 * Simple test of glInterleavedArrays functionality.  For each mode, two
29 * meshes are drawn.  One is drawn using interleaved arrays and the othe is
30 * drawn using immediate mode.  Both should look identical.
31 *
32 * \author Ian Romanick <idr@us.ibm.com>
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <time.h>
39#include <GL/glew.h>
40#include "glut_wrap.h"
41
42static int Width = 400;
43static int Height = 300;
44static const GLfloat Near = 5.0, Far = 25.0;
45
46static const GLfloat t[][4] = {
47   { 0.5,  0.0, 0.0, 1.0 },
48
49   { 0.25, 0.5, 0.0, 1.0 },
50   { 0.75, 0.5, 0.0, 1.0 },
51
52   { 0.0,  1.0, 0.0, 1.0 },
53   { 0.5,  1.0, 0.0, 1.0 },
54   { 1.0,  1.0, 0.0, 1.0 },
55};
56
57static const GLfloat c_f[][4] = {
58   { 1.0, 0.0, 0.0, 1.0 },
59
60   { 0.0, 1.0, 0.0, 1.0 },
61   { 0.0, 1.0, 0.0, 1.0 },
62
63   { 0.0, 0.0, 1.0, 1.0 },
64   { 1.0, 0.0, 1.0, 1.0 },
65   { 0.0, 0.0, 1.0, 1.0 },
66};
67
68static const GLubyte c_ub[][4] = {
69   { 0xff, 0x00, 0x00, 0xff },
70
71   { 0x00, 0xff, 0x00, 0xff },
72   { 0x00, 0xff, 0x00, 0xff },
73
74   { 0x00, 0x00, 0xff, 0xff },
75   { 0xff, 0x00, 0xff, 0xff },
76   { 0x00, 0x00, 0xff, 0xff },
77};
78
79static const GLfloat n[][3] = {
80   { 0.0, 0.0, -1.0 },
81
82   { 0.0, 0.0, -1.0 },
83   { 0.0, 0.0, -1.0 },
84
85   { 0.0, 0.0, -1.0 },
86   { 0.0, 0.0, -1.0 },
87   { 0.0, 0.0, -1.0 },
88};
89
90static const GLfloat v[][4] = {
91   {  0.0,  1.0, 0.0, 1.0, },
92
93   { -0.5,  0.0, 0.0, 1.0, },
94   {  0.5,  0.0, 0.0, 1.0, },
95
96   { -1.0, -1.0, 0.0, 1.0, },
97   {  0.0, -1.0, 0.0, 1.0, },
98   {  1.0, -1.0, 0.0, 1.0, },
99};
100
101static const unsigned indicies[12] = {
102   0, 1, 2,
103   1, 3, 4,
104   2, 4, 5,
105   1, 4, 2
106};
107
108#define NONE  { NULL, 0, 0, 0, sizeof( NULL ) }
109#define V2F   { v,    2, 2 * sizeof( GLfloat ), GL_FLOAT, sizeof( v[0] ) }
110#define V3F   { v,    3, 3 * sizeof( GLfloat ), GL_FLOAT, sizeof( v[0] ) }
111#define V4F   { v,    4, 4 * sizeof( GLfloat ), GL_FLOAT, sizeof( v[0] ) }
112
113#define C4UB  { c_ub, 4, 4 * sizeof( GLubyte ), GL_UNSIGNED_BYTE, sizeof( c_ub[0] ) }
114#define C3F   { c_f,  3, 3 * sizeof( GLfloat ), GL_FLOAT,         sizeof( c_f[0] ) }
115#define C4F   { c_f,  4, 4 * sizeof( GLfloat ), GL_FLOAT,         sizeof( c_f[0] ) }
116
117#define T2F   { t,    2, 2 * sizeof( GLfloat ), GL_FLOAT, sizeof( t[0] ) }
118#define T4F   { t,    4, 4 * sizeof( GLfloat ), GL_FLOAT, sizeof( t[0] ) }
119
120#define N3F   { n,    3, 3 * sizeof( GLfloat ), GL_FLOAT, sizeof( n[0] ) }
121
122struct interleave_info {
123   const void * data;
124   unsigned count;
125   unsigned size;
126   GLenum type;
127   unsigned stride;
128};
129
130#define NUM_MODES      14
131#define INVALID_MODE   14
132#define INVALID_STRIDE 15
133
134struct interleave_info info[ NUM_MODES ][4] = {
135   { NONE, NONE, NONE, V2F },
136   { NONE, NONE, NONE, V3F },
137   { NONE, C4UB, NONE, V2F },
138   { NONE, C4UB, NONE, V3F },
139   { NONE, C3F,  NONE, V3F },
140
141   { NONE, NONE, N3F,  V3F },
142   { NONE, C4F,  N3F,  V3F },
143
144   { T2F,  NONE, NONE, V3F },
145   { T4F,  NONE, NONE, V4F },
146
147   { T2F,  C4UB, NONE, V3F },
148   { T2F,  C3F,  NONE, V3F },
149   { T2F,  NONE, N3F,  V3F },
150   { T2F,  C4F,  N3F,  V3F },
151   { T4F,  C4F,  N3F,  V4F },
152};
153
154const char * const mode_names[ NUM_MODES ] = {
155   "GL_V2F",
156   "GL_V3F",
157   "GL_C4UB_V2F",
158   "GL_C4UB_V3F",
159   "GL_C3F_V3F",
160   "GL_N3F_V3F",
161   "GL_C4F_N3F_V3F",
162   "GL_T2F_V3F",
163   "GL_T4F_V4F",
164   "GL_T2F_C4UB_V3F",
165   "GL_T2F_C3F_V3F",
166   "GL_T2F_N3F_V3F",
167   "GL_T2F_C4F_N3F_V3F",
168   "GL_T4F_C4F_N3F_V4F",
169};
170
171static unsigned interleave_mode = 0;
172static GLboolean use_invalid_mode = GL_FALSE;
173static GLboolean use_invalid_stride = GL_FALSE;
174
175#define DEREF(item,idx) (void *) & ((char *)curr_info[item].data)[idx * curr_info[item].stride]
176
177static void Display( void )
178{
179   const struct interleave_info * const curr_info = info[ interleave_mode ];
180
181   /* 4 floats for 12 verticies for 4 data elements.
182    */
183   char data[ (sizeof( GLfloat ) * 4) * 12 * 4 ];
184
185   unsigned i;
186   unsigned offset;
187   GLenum err;
188   GLenum format;
189   GLsizei stride;
190
191
192   glClearColor(0.2, 0.2, 0.8, 0);
193   glClear( GL_COLOR_BUFFER_BIT );
194
195   glPushMatrix();
196
197   glTranslatef(-1.5, 0, 0);
198
199   glColor3fv( c_f[0] );
200
201   if ( curr_info[0].data != NULL ) {
202      glEnable( GL_TEXTURE_2D );
203   }
204   else {
205      glDisable( GL_TEXTURE_2D );
206   }
207
208
209   offset = 0;
210   glBegin(GL_TRIANGLES);
211   for ( i = 0 ; i < 12 ; i++ ) {
212      const unsigned index = indicies[i];
213
214
215      /* Handle the vertex texture coordinate.
216       */
217      if ( curr_info[0].data != NULL ) {
218	 if ( curr_info[0].count == 2 ) {
219	    glTexCoord2fv( DEREF(0, index) );
220	 }
221	 else {
222	    glTexCoord4fv( DEREF(0, index) );
223	 }
224
225	 (void) memcpy( & data[ offset ], DEREF(0, index),
226			curr_info[0].size );
227	 offset += curr_info[0].size;
228      }
229
230
231      /* Handle the vertex color.
232       */
233      if ( curr_info[1].data != NULL ) {
234	 if ( curr_info[1].type == GL_FLOAT ) {
235	    if ( curr_info[1].count == 3 ) {
236	       glColor3fv( DEREF(1, index) );
237	    }
238	    else {
239	       glColor4fv( DEREF(1, index) );
240	    }
241	 }
242	 else {
243	    glColor4ubv( DEREF(1, index) );
244	 }
245
246	 (void) memcpy( & data[ offset ], DEREF(1, index),
247			curr_info[1].size );
248	 offset += curr_info[1].size;
249      }
250
251
252      /* Handle the vertex normal.
253       */
254      if ( curr_info[2].data != NULL ) {
255	 glNormal3fv( DEREF(2, index) );
256
257	 (void) memcpy( & data[ offset ], DEREF(2, index),
258			curr_info[2].size );
259	 offset += curr_info[2].size;
260      }
261
262
263      switch( curr_info[3].count ) {
264      case 2:
265	 glVertex2fv( DEREF(3, index) );
266	 break;
267      case 3:
268	 glVertex3fv( DEREF(3, index) );
269	 break;
270      case 4:
271	 glVertex4fv( DEREF(3, index) );
272	 break;
273      }
274
275      (void) memcpy( & data[ offset ], DEREF(3, index),
276		     curr_info[3].size );
277	 offset += curr_info[3].size;
278   }
279   glEnd();
280
281
282   glTranslatef(3.0, 0, 0);
283
284   /* The masking with ~0x2A00 is a bit of a hack to make sure that format
285    * ends up with an invalid value no matter what rand() returns.
286    */
287   format = (use_invalid_mode)
288     ? (rand() & ~0x2A00) : GL_V2F + interleave_mode;
289   stride = (use_invalid_stride) ? -abs(rand()) : 0;
290
291   (void) glGetError();
292   glInterleavedArrays( format, stride, data );
293   err = glGetError();
294   if ( err ) {
295      printf("glInterleavedArrays(0x%04x, %d, %p) generated the error 0x%04x\n",
296	     format, stride, data, err );
297   }
298   else {
299      glDrawArrays( GL_TRIANGLES, 0, 12 );
300   }
301
302   glPopMatrix();
303
304   glutSwapBuffers();
305}
306
307
308static void Reshape( int width, int height )
309{
310   GLfloat ar = (float) width / (float) height;
311   Width = width;
312   Height = height;
313   glViewport( 0, 0, width, height );
314   glMatrixMode( GL_PROJECTION );
315   glLoadIdentity();
316   glFrustum( -ar, ar, -1.0, 1.0, Near, Far );
317   glMatrixMode( GL_MODELVIEW );
318   glLoadIdentity();
319   glTranslatef( 0.0, 0.0, -15.0 );
320}
321
322
323static void Key( unsigned char key, int x, int y )
324{
325   (void) x;
326   (void) y;
327   switch (key) {
328      case 27:
329         exit(0);
330         break;
331   }
332   glutPostRedisplay();
333}
334
335
336static void ModeMenu( int entry )
337{
338   if ( entry == INVALID_MODE ) {
339      use_invalid_mode = GL_TRUE;
340      use_invalid_stride = GL_FALSE;
341   }
342   else if ( entry == INVALID_STRIDE ) {
343      use_invalid_mode = GL_FALSE;
344      use_invalid_stride = GL_TRUE;
345   }
346   else {
347      use_invalid_mode = GL_FALSE;
348      use_invalid_stride = GL_FALSE;
349      interleave_mode = entry;
350   }
351}
352
353static void Init( void )
354{
355   const char * const ver_string = (const char *)
356       glGetString( GL_VERSION );
357   const GLubyte tex[16] = {
358      0xff, 0x00, 0xff, 0x00,
359      0x00, 0xff, 0x00, 0xff,
360      0xff, 0x00, 0xff, 0x00,
361      0x00, 0xff, 0x00, 0xff,
362   };
363
364   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
365   printf("GL_VERSION = %s\n", ver_string);
366
367   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
368   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
369   glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
370   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0,
371		 GL_LUMINANCE, GL_UNSIGNED_BYTE, tex );
372
373   printf("Use the context menu (right click) to select the interleaved array mode.\n");
374   printf("Press ESCAPE to exit.\n\n");
375   printf("NOTE: This is *NOT* a very good test of the modes that use normals.\n");
376}
377
378
379int main( int argc, char *argv[] )
380{
381   unsigned i;
382
383   srand( time( NULL ) );
384
385   glutInit( &argc, argv );
386   glutInitWindowPosition( 0, 0 );
387   glutInitWindowSize( Width, Height );
388   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
389   glutCreateWindow( "glInterleavedArrays test" );
390   glewInit();
391   glutReshapeFunc( Reshape );
392   glutKeyboardFunc( Key );
393   glutDisplayFunc( Display );
394
395   glutCreateMenu( ModeMenu );
396   for ( i = 0 ; i < NUM_MODES ; i++ ) {
397      glutAddMenuEntry( mode_names[i], i);
398   }
399
400   glutAddMenuEntry( "Random invalid mode",   INVALID_MODE);
401   glutAddMenuEntry( "Random invalid stride", INVALID_STRIDE);
402
403   glutAttachMenu(GLUT_RIGHT_BUTTON);
404
405   Init();
406   glutMainLoop();
407   return 0;
408}
409