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