lots of debug options, some code movement, etc
[mesa.git] / progs / tests / fbotexture.c
1 /*
2 * Test GL_EXT_framebuffer_object render-to-texture
3 *
4 * Draw a teapot into a texture image with stenciling.
5 * Then draw a textured quad using that texture.
6 *
7 * Brian Paul
8 * 18 Apr 2005
9 */
10
11
12 #define GL_GLEXT_PROTOTYPES
13 #include <GL/glut.h>
14 #include <assert.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19
20 /* For debug */
21 #define DEPTH 1
22 #define STENCIL 1
23 #define DRAW 1
24
25
26 static int Width = 400, Height = 400;
27
28 static GLenum TexTarget = GL_TEXTURE_2D; /*GL_TEXTURE_RECTANGLE_ARB;*/
29 static int TexWidth = 512, TexHeight = 512;
30 /*static int TexWidth = 600, TexHeight = 600;*/
31
32 static GLuint MyFB;
33 static GLuint TexObj;
34 static GLuint DepthRB, StencilRB;
35 static GLboolean Anim = GL_FALSE;
36 static GLfloat Rot = 0.0;
37 static GLboolean UsePackedDepthStencil = GL_FALSE;
38 static GLuint TextureLevel = 1; /* which texture level to render to */
39 static GLenum TexIntFormat = GL_RGB; /* either GL_RGB or GL_RGBA */
40
41
42 static void
43 CheckError(int line)
44 {
45 GLenum err = glGetError();
46 if (err) {
47 printf("GL Error 0x%x at line %d\n", (int) err, line);
48 }
49 }
50
51
52 static void
53 Idle(void)
54 {
55 Rot = glutGet(GLUT_ELAPSED_TIME) * 0.1;
56 glutPostRedisplay();
57 }
58
59
60 static void
61 RenderTexture(void)
62 {
63 GLenum status;
64
65 glMatrixMode(GL_PROJECTION);
66 glLoadIdentity();
67 glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
68 glMatrixMode(GL_MODELVIEW);
69 glLoadIdentity();
70 glTranslatef(0.0, 0.0, -15.0);
71
72 /* draw to texture image */
73 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
74
75 status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
76 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
77 printf("Framebuffer incomplete!!!\n");
78 }
79
80 glViewport(0, 0, TexWidth, TexHeight);
81
82 glClearColor(0.5, 0.5, 1.0, 0.0);
83 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
84 CheckError(__LINE__);
85
86 #if DEPTH
87 glEnable(GL_DEPTH_TEST);
88 #endif
89
90 #if STENCIL
91 glEnable(GL_STENCIL_TEST);
92 glStencilFunc(GL_NEVER, 1, ~0);
93 glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
94 #endif
95
96 CheckError(__LINE__);
97
98 #if DEPTH || STENCIL
99 /* draw diamond-shaped stencil pattern */
100 glColor3f(0, 1, 0);
101 glBegin(GL_POLYGON);
102 glVertex2f(-0.2, 0.0);
103 glVertex2f( 0.0, -0.2);
104 glVertex2f( 0.2, 0.0);
105 glVertex2f( 0.0, 0.2);
106 glEnd();
107 #endif
108
109 /* draw teapot where stencil != 1 */
110 #if STENCIL
111 glStencilFunc(GL_NOTEQUAL, 1, ~0);
112 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
113 #endif
114
115 CheckError(__LINE__);
116
117 #if 0
118 glBegin(GL_POLYGON);
119 glColor3f(1, 0, 0);
120 glVertex2f(-1, -1);
121 glColor3f(0, 1, 0);
122 glVertex2f(1, -1);
123 glColor3f(0, 0, 1);
124 glVertex2f(0, 1);
125 glEnd();
126 #else
127 glEnable(GL_LIGHTING);
128 glEnable(GL_LIGHT0);
129 glPushMatrix();
130 glRotatef(0.5 * Rot, 1.0, 0.0, 0.0);
131 glutSolidTeapot(0.5);
132 glPopMatrix();
133 glDisable(GL_LIGHTING);
134 /*
135 PrintStencilHistogram(TexWidth, TexHeight);
136 */
137 #endif
138
139 glDisable(GL_DEPTH_TEST);
140 glDisable(GL_STENCIL_TEST);
141
142 #if DRAW
143 /* Bind normal framebuffer */
144 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
145 #endif
146
147 CheckError(__LINE__);
148 }
149
150
151
152 static void
153 Display(void)
154 {
155 float ar = (float) Width / (float) Height;
156
157 RenderTexture();
158
159 /* draw textured quad in the window */
160 #if DRAW
161 glMatrixMode(GL_PROJECTION);
162 glLoadIdentity();
163 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 25.0);
164 glMatrixMode(GL_MODELVIEW);
165 glLoadIdentity();
166 glTranslatef(0.0, 0.0, -7.0);
167
168 glViewport(0, 0, Width, Height);
169
170 glClearColor(0.25, 0.25, 0.25, 0);
171 glClear(GL_COLOR_BUFFER_BIT);
172
173 glPushMatrix();
174 glRotatef(Rot, 0, 1, 0);
175 glEnable(TexTarget);
176 glBindTexture(TexTarget, TexObj);
177 glBegin(GL_POLYGON);
178 glColor3f(0.25, 0.25, 0.25);
179 if (TexTarget == GL_TEXTURE_2D) {
180 glTexCoord2f(0, 0);
181 glVertex2f(-1, -1);
182 glTexCoord2f(1, 0);
183 glVertex2f(1, -1);
184 glColor3f(1.0, 1.0, 1.0);
185 glTexCoord2f(1, 1);
186 glVertex2f(1, 1);
187 glTexCoord2f(0, 1);
188 glVertex2f(-1, 1);
189 }
190 else {
191 assert(TexTarget == GL_TEXTURE_RECTANGLE_ARB);
192 glTexCoord2f(0, 0);
193 glVertex2f(-1, -1);
194 glTexCoord2f(TexWidth, 0);
195 glVertex2f(1, -1);
196 glColor3f(1.0, 1.0, 1.0);
197 glTexCoord2f(TexWidth, TexHeight);
198 glVertex2f(1, 1);
199 glTexCoord2f(0, TexHeight);
200 glVertex2f(-1, 1);
201 }
202 glEnd();
203 glPopMatrix();
204 glDisable(TexTarget);
205 #endif
206
207 glutSwapBuffers();
208 CheckError(__LINE__);
209 }
210
211
212 static void
213 Reshape(int width, int height)
214 {
215 glViewport(0, 0, width, height);
216 Width = width;
217 Height = height;
218 }
219
220
221 static void
222 CleanUp(void)
223 {
224 #if DEPTH
225 glDeleteRenderbuffersEXT(1, &DepthRB);
226 #endif
227 #if STENCIL
228 if (!UsePackedDepthStencil)
229 glDeleteRenderbuffersEXT(1, &StencilRB);
230 #endif
231 glDeleteFramebuffersEXT(1, &MyFB);
232
233 glDeleteTextures(1, &TexObj);
234
235 exit(0);
236 }
237
238
239 static void
240 Key(unsigned char key, int x, int y)
241 {
242 (void) x;
243 (void) y;
244 switch (key) {
245 case 'a':
246 Anim = !Anim;
247 if (Anim)
248 glutIdleFunc(Idle);
249 else
250 glutIdleFunc(NULL);
251 break;
252 case 's':
253 Rot += 2.0;
254 break;
255 case 27:
256 CleanUp();
257 break;
258 }
259 glutPostRedisplay();
260 }
261
262
263 static void
264 Init(int argc, char *argv[])
265 {
266 static const GLfloat mat[4] = { 1.0, 0.5, 0.5, 1.0 };
267 GLint i;
268
269 if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
270 printf("GL_EXT_framebuffer_object not found!\n");
271 exit(0);
272 }
273
274 if (argc > 1 && strcmp(argv[1], "-ds") == 0) {
275 if (!glutExtensionSupported("GL_EXT_packed_depth_stencil")) {
276 printf("GL_EXT_packed_depth_stencil not found!\n");
277 exit(0);
278 }
279 UsePackedDepthStencil = GL_TRUE;
280 printf("Using GL_EXT_packed_depth_stencil\n");
281 }
282
283 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
284
285 /* gen framebuffer id, delete it, do some assertions, just for testing */
286 glGenFramebuffersEXT(1, &MyFB);
287 assert(MyFB);
288 assert(!glIsFramebufferEXT(MyFB));
289 glDeleteFramebuffersEXT(1, &MyFB);
290 assert(!glIsFramebufferEXT(MyFB));
291 /* Note, continue to use MyFB below */
292
293 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB);
294 assert(glIsFramebufferEXT(MyFB));
295 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &i);
296 assert(i == MyFB);
297
298 /* Make texture object/image */
299 glGenTextures(1, &TexObj);
300 glBindTexture(TexTarget, TexObj);
301 /* make two image levels */
302 glTexImage2D(TexTarget, 0, TexIntFormat, TexWidth, TexHeight, 0,
303 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
304 glTexImage2D(TexTarget, 1, TexIntFormat, TexWidth/2, TexHeight/2, 0,
305 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
306 TexWidth = TexWidth >> TextureLevel;
307 TexHeight = TexHeight >> TextureLevel;
308
309 glTexParameteri(TexTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
310 glTexParameteri(TexTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
311 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
312 glTexParameteri(TexTarget, GL_TEXTURE_BASE_LEVEL, TextureLevel);
313 glTexParameteri(TexTarget, GL_TEXTURE_MAX_LEVEL, TextureLevel);
314
315 CheckError(__LINE__);
316
317 /* Render color to texture */
318 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
319 TexTarget, TexObj, TextureLevel);
320
321
322 #if DEPTH
323 /* make depth renderbuffer */
324 glGenRenderbuffersEXT(1, &DepthRB);
325 assert(DepthRB);
326 assert(!glIsRenderbufferEXT(DepthRB));
327 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthRB);
328 assert(glIsRenderbufferEXT(DepthRB));
329 if (UsePackedDepthStencil)
330 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT,
331 TexWidth, TexHeight);
332 else
333 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
334 TexWidth, TexHeight);
335 CheckError(__LINE__);
336 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
337 GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
338 CheckError(__LINE__);
339 printf("Depth renderbuffer size = %d bits\n", i);
340 assert(i > 0);
341
342 /* attach DepthRB to MyFB */
343 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
344 GL_RENDERBUFFER_EXT, DepthRB);
345 #endif
346
347 CheckError(__LINE__);
348
349 #if STENCIL
350 if (UsePackedDepthStencil) {
351 /* DepthRb is a combined depth/stencil renderbuffer */
352 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
353 GL_STENCIL_ATTACHMENT_EXT,
354 GL_RENDERBUFFER_EXT, DepthRB);
355 }
356 else {
357 /* make stencil renderbuffer */
358 glGenRenderbuffersEXT(1, &StencilRB);
359 assert(StencilRB);
360 assert(!glIsRenderbufferEXT(StencilRB));
361 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilRB);
362 assert(glIsRenderbufferEXT(StencilRB));
363 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX,
364 TexWidth, TexHeight);
365 /* attach StencilRB to MyFB */
366 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
367 GL_STENCIL_ATTACHMENT_EXT,
368 GL_RENDERBUFFER_EXT, StencilRB);
369 }
370 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT,
371 GL_RENDERBUFFER_STENCIL_SIZE_EXT, &i);
372 CheckError(__LINE__);
373 printf("Stencil renderbuffer size = %d bits\n", i);
374 assert(i > 0);
375 #endif
376
377 CheckError(__LINE__);
378
379 /* bind regular framebuffer */
380 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
381
382
383 /* lighting */
384 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
385 }
386
387
388 int
389 main(int argc, char *argv[])
390 {
391 glutInit(&argc, argv);
392 glutInitWindowPosition(0, 0);
393 glutInitWindowSize(Width, Height);
394 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
395 glutCreateWindow(argv[0]);
396 glutReshapeFunc(Reshape);
397 glutKeyboardFunc(Key);
398 glutDisplayFunc(Display);
399 if (Anim)
400 glutIdleFunc(Idle);
401 Init(argc, argv);
402 glutMainLoop();
403 return 0;
404 }