1/*
2 * GL_ARB_occlusion_query(2) demo
3 *
4 * Brian Paul
5 * 12 June 2003
6 *
7 * Copyright (C) 2003  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Enhanced by Dave Airlie to add ARB_occlusion_query2
27 */
28
29#include <assert.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <math.h>
34#include <GL/glew.h>
35#include "glut_wrap.h"
36
37static GLboolean Anim = GL_TRUE;
38static GLfloat Xpos = 0;
39static GLuint OccQuery1;
40#if defined(GL_ARB_occlusion_query2)
41static GLuint OccQuery2;
42#endif
43static GLint Win = 0;
44static GLboolean has_oq2 = GL_FALSE;
45
46
47static void
48PrintString(const char *s)
49{
50   while (*s) {
51      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
52      s++;
53   }
54}
55
56
57
58static void Idle(void)
59{
60   static int lastTime = 0;
61   static int sign = +1;
62   int time = glutGet(GLUT_ELAPSED_TIME);
63   float step;
64
65   if (lastTime == 0)
66      lastTime = time;
67   else if (time - lastTime < 20)  /* 50Hz update */
68      return;
69
70   step = (time - lastTime) / 1000.0 * sign;
71   lastTime = time;
72
73   Xpos += step;
74
75   if (Xpos > 2.5) {
76      Xpos = 2.5;
77      sign = -1;
78   }
79   else if (Xpos < -2.5) {
80      Xpos = -2.5;
81      sign = +1;
82   }
83   glutPostRedisplay();
84}
85
86
87static void Display( void )
88{
89   GLuint passed1;
90#if defined(GL_ARB_occlusion_query2)
91   GLuint passed2_boolean;
92#endif
93   GLint ready;
94   char s[100];
95
96   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
97
98   glMatrixMode( GL_PROJECTION );
99   glLoadIdentity();
100   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
101   glMatrixMode( GL_MODELVIEW );
102   glLoadIdentity();
103   glTranslatef( 0.0, 0.0, -15.0 );
104
105   /* draw the occluding polygons */
106   glColor3f(0, 0.6, 0.8);
107   glBegin(GL_QUADS);
108   glVertex2f(-1.6, -1.5);
109   glVertex2f(-0.4, -1.5);
110   glVertex2f(-0.4,  1.5);
111   glVertex2f(-1.6,  1.5);
112
113   glVertex2f( 0.4, -1.5);
114   glVertex2f( 1.6, -1.5);
115   glVertex2f( 1.6,  1.5);
116   glVertex2f( 0.4,  1.5);
117   glEnd();
118
119#if defined(GL_ARB_occlusion_query)
120   /* disable all buffer updates */
121   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
122   glDepthMask(GL_FALSE);
123
124   /* draw the first polygon with occlusion testing */
125   glPushMatrix();
126      glTranslatef(Xpos, 0.4, -0.5);
127      glScalef(0.3, 0.3, 1.0);
128      glRotatef(-90.0 * Xpos, 0, 0, 1);
129
130      glBeginQueryARB(GL_SAMPLES_PASSED_ARB, OccQuery1);
131
132      glBegin(GL_POLYGON);
133      glVertex3f(-1, -1, 0);
134      glVertex3f( 1, -1, 0);
135      glVertex3f( 1,  1, 0);
136      glVertex3f(-1,  1, 0);
137      glEnd();
138
139      glEndQueryARB(GL_SAMPLES_PASSED_ARB);
140   glPopMatrix();
141#endif
142
143   /* draw the second polygon with occlusion testing */
144   glPushMatrix();
145      glTranslatef(Xpos, -0.4, -0.5);
146      glScalef(0.3, 0.3, 1.0);
147#if defined(GL_ARB_occlusion_query2)
148      if (has_oq2) {
149         glBeginQueryARB(GL_ANY_SAMPLES_PASSED, OccQuery2);
150
151         glBegin(GL_POLYGON);
152         glVertex3f(-1, -1, 0);
153         glVertex3f( 1, -1, 0);
154         glVertex3f( 1,  1, 0);
155         glVertex3f(-1,  1, 0);
156         glEnd();
157
158         glEndQueryARB(GL_ANY_SAMPLES_PASSED);
159      }
160#endif
161
162      /* re-enable buffer updates */
163      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
164      glDepthMask(GL_TRUE);
165
166#if defined(GL_ARB_occlusion_query)
167      do {
168         /* do useful work here, if any */
169         glGetQueryObjectivARB(OccQuery1, GL_QUERY_RESULT_AVAILABLE_ARB, &ready);
170      } while (!ready);
171      glGetQueryObjectuivARB(OccQuery1, GL_QUERY_RESULT_ARB, &passed1);
172#endif
173#if defined(GL_ARB_occlusion_query2)
174      if (has_oq2) {
175         do {
176            /* do useful work here, if any */
177            glGetQueryObjectivARB(OccQuery2, GL_QUERY_RESULT_AVAILABLE_ARB, &ready);
178         } while (!ready);
179         glGetQueryObjectuivARB(OccQuery2, GL_QUERY_RESULT_ARB, &passed2_boolean);
180      }
181#endif /* GL_ARB_occlusion_query2 */
182
183      /* draw the second rect, so we can see what's going on */
184      glColor3f(0.8, 0.5, 0);
185      if (has_oq2) {
186         glBegin(GL_POLYGON);
187         glVertex3f(-1, -1, 0);
188         glVertex3f( 1, -1, 0);
189         glVertex3f( 1,  1, 0);
190         glVertex3f(-1,  1, 0);
191         glEnd();
192      }
193   glPopMatrix();
194
195   glPushMatrix();
196      glTranslatef(Xpos, 0.4, -0.5);
197      glScalef(0.3, 0.3, 1.0);
198      glRotatef(-90.0 * Xpos, 0, 0, 1);
199
200      /* draw the first rect, so we can see what's going on */
201      glBegin(GL_POLYGON);
202      glVertex3f(-1, -1, 0);
203      glVertex3f( 1, -1, 0);
204      glVertex3f( 1,  1, 0);
205      glVertex3f(-1,  1, 0);
206      glEnd();
207   glPopMatrix();
208
209   /* Print result message */
210   glMatrixMode( GL_PROJECTION );
211   glLoadIdentity();
212   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
213   glMatrixMode( GL_MODELVIEW );
214   glLoadIdentity();
215
216   glColor3f(1, 1, 1);
217#if defined(GL_ARB_occlusion_query)
218   sprintf(s, " %4d Fragments Visible", passed1);
219   glRasterPos3f(-0.50, -0.6, 0);
220   PrintString(s);
221   if (!passed1) {
222      glRasterPos3f(-0.25, -0.7, 0);
223      PrintString("Fully Occluded");
224   }
225#if defined(GL_ARB_occlusion_query2)
226   if (has_oq2) {
227      glRasterPos3f(-0.25, -0.9, 0);
228      if (!passed2_boolean) {
229         PrintString("Fully Occluded");
230      } else {
231         PrintString("Partly Visible");
232      }
233   }
234#endif
235#else
236   glRasterPos3f(-0.25, -0.8, 0);
237   PrintString("GL_ARB_occlusion_query not available at compile time");
238#endif /* GL_ARB_occlusion_query */
239
240   glutSwapBuffers();
241}
242
243
244static void Reshape( int width, int height )
245{
246   glViewport( 0, 0, width, height );
247}
248
249
250static void Key( unsigned char key, int x, int y )
251{
252   (void) x;
253   (void) y;
254   switch (key) {
255      case 27:
256         glutDestroyWindow(Win);
257         exit(0);
258         break;
259      case ' ':
260         Anim = !Anim;
261         if (Anim)
262            glutIdleFunc(Idle);
263         else
264            glutIdleFunc(NULL);
265         break;
266   }
267   glutPostRedisplay();
268}
269
270
271static void SpecialKey( int key, int x, int y )
272{
273   const GLfloat step = 0.1;
274   (void) x;
275   (void) y;
276   switch (key) {
277      case GLUT_KEY_LEFT:
278         Xpos -= step;
279         break;
280      case GLUT_KEY_RIGHT:
281         Xpos += step;
282         break;
283   }
284   glutPostRedisplay();
285}
286
287
288static void Init( void )
289{
290   const char *ext = (const char *) glGetString(GL_EXTENSIONS);
291   GLint bits;
292
293   if (!strstr(ext, "GL_ARB_occlusion_query")) {
294      printf("Sorry, this demo requires the GL_ARB_occlusion_query extension\n");
295      exit(-1);
296   }
297
298   if (strstr(ext, "GL_ARB_occlusion_query2")) {
299      has_oq2 = GL_TRUE;
300      printf("OQ2 supported\n");
301   }
302#if defined(GL_ARB_occlusion_query)
303   glGetQueryivARB(GL_SAMPLES_PASSED_ARB, GL_QUERY_COUNTER_BITS_ARB, &bits);
304   if (!bits) {
305      printf("Hmmm, GL_QUERY_COUNTER_BITS_ARB is zero!\n");
306      exit(-1);
307   }
308#endif /* GL_ARB_occlusion_query */
309
310   glGetIntegerv(GL_DEPTH_BITS, &bits);
311   printf("Depthbits: %d\n", bits);
312
313#if defined(GL_ARB_occlusion_query)
314   glGenQueriesARB(1, &OccQuery1);
315   assert(OccQuery1 > 0);
316#if defined(GL_ARB_occlusion_query2)
317   if (has_oq2) {
318      glGenQueriesARB(1, &OccQuery2);
319      assert(OccQuery2 > 0);
320   }
321#endif
322#endif /* GL_ARB_occlusion_query */
323
324   glEnable(GL_DEPTH_TEST);
325}
326
327
328int main( int argc, char *argv[] )
329{
330   glutInitWindowSize( 400, 400 );
331   glutInit( &argc, argv );
332   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
333   Win = glutCreateWindow(argv[0]);
334   glewInit();
335   glutReshapeFunc( Reshape );
336   glutKeyboardFunc( Key );
337   glutSpecialFunc( SpecialKey );
338   glutIdleFunc( Idle );
339   glutDisplayFunc( Display );
340   Init();
341   glutMainLoop();
342   return 0;
343}
344