Merge remote branch 'origin/master' into lp-binning
[mesa.git] / progs / tests / drawbuffers2.c
1 /*
2 * Test GL_ARB_draw_buffers2, GL_ARB_draw_buffers, GL_EXT_framebuffer_object
3 * and GLSL's gl_FragData[].
4 *
5 * We draw to two color buffers and show the left half of the first
6 * color buffer on the left side of the window, and show the right
7 * half of the second color buffer on the right side of the window.
8 *
9 * Different color masks are used for the two color buffers.
10 * Blending is enabled for the second buffer only.
11 *
12 * Brian Paul
13 * 31 Dec 2009
14 */
15
16
17 #include <assert.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <math.h>
21 #include <GL/glew.h>
22 #include <GL/glut.h>
23 #include "extfuncs.h"
24
25 static int Win;
26 static int Width = 400, Height = 400;
27 static GLuint FBobject, RBobjects[3];
28 static GLfloat Xrot = 0.0, Yrot = 0.0;
29 static GLuint Program;
30 static GLboolean Anim = GL_TRUE;
31
32
33 static void
34 CheckError(int line)
35 {
36 GLenum err = glGetError();
37 if (err) {
38 printf("GL Error 0x%x at line %d\n", (int) err, line);
39 }
40 }
41
42
43 static void
44 Display(void)
45 {
46 GLubyte *buffer = malloc(Width * Height * 4);
47 static const GLenum buffers[2] = {
48 GL_COLOR_ATTACHMENT0_EXT,
49 GL_COLOR_ATTACHMENT1_EXT
50 };
51
52 glUseProgram_func(Program);
53
54 glEnable(GL_DEPTH_TEST);
55
56 /* draw to user framebuffer */
57 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
58
59 /* Clear color buffer 0 (blue) */
60 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
61 glClear(GL_COLOR_BUFFER_BIT);
62
63 /* Clear color buffer 1 (1 - blue) */
64 glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
65 glClear(GL_COLOR_BUFFER_BIT);
66
67 glClear(GL_DEPTH_BUFFER_BIT);
68
69 /* draw to two buffers w/ fragment shader */
70 glDrawBuffersARB(2, buffers);
71
72 /* different color masks for each buffer */
73 if (1) {
74 glColorMaskIndexedEXT(0, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
75 glColorMaskIndexedEXT(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
76 }
77
78 glPushMatrix();
79 glRotatef(Xrot, 1, 0, 0);
80 glRotatef(Yrot, 0, 1, 0);
81 glPushMatrix();
82 glTranslatef(1, 0, 0);
83 glutSolidTorus(1.0, 2.0, 10, 20);
84 glPopMatrix();
85 glPushMatrix();
86 glTranslatef(-1, 0, 0);
87 glRotatef(90, 1, 0, 0);
88 glutSolidTorus(1.0, 2.0, 10, 20);
89 glPopMatrix();
90 glPopMatrix();
91
92 /* restore default color masks */
93 glColorMaskIndexedEXT(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
94 glColorMaskIndexedEXT(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
95
96 /* read from user framebuffer */
97 /* left half = colorbuffer 0 */
98 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
99 glPixelStorei(GL_PACK_ROW_LENGTH, Width);
100 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
101 glReadPixels(0, 0, Width / 2, Height, GL_RGBA, GL_UNSIGNED_BYTE,
102 buffer);
103
104 /* right half = colorbuffer 1 */
105 glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
106 glPixelStorei(GL_PACK_SKIP_PIXELS, Width / 2);
107 glReadPixels(Width / 2, 0, Width - Width / 2, Height,
108 GL_RGBA, GL_UNSIGNED_BYTE,
109 buffer);
110
111 /* draw to window */
112 glUseProgram_func(0);
113 glDisable(GL_DEPTH_TEST);
114 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
115 glWindowPos2iARB(0, 0);
116 glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
117
118 free(buffer);
119 glutSwapBuffers();
120 CheckError(__LINE__);
121 }
122
123
124 static void
125 Idle(void)
126 {
127 Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.05;
128 glutPostRedisplay();
129 }
130
131
132 static void
133 Reshape(int width, int height)
134 {
135 float ar = (float) width / (float) height;
136
137 glViewport(0, 0, width, height);
138 glMatrixMode(GL_PROJECTION);
139 glLoadIdentity();
140 glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0);
141 glMatrixMode(GL_MODELVIEW);
142 glLoadIdentity();
143 glTranslatef(0.0, 0.0, -20.0);
144
145 Width = width;
146 Height = height;
147
148 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
149 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
150 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
151 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
152 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
153 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
154 Width, Height);
155 }
156
157
158 static void
159 CleanUp(void)
160 {
161 glDeleteFramebuffersEXT(1, &FBobject);
162 glDeleteRenderbuffersEXT(3, RBobjects);
163 glutDestroyWindow(Win);
164 exit(0);
165 }
166
167
168 static void
169 Key(unsigned char key, int x, int y)
170 {
171 (void) x;
172 (void) y;
173 switch (key) {
174 case ' ':
175 Anim = !Anim;
176 glutIdleFunc(Anim ? Idle : NULL);
177 break;
178 case 'x':
179 Xrot += 5.0;
180 break;
181 case 'X':
182 Xrot -= 5.0;
183 break;
184 case 'y':
185 Yrot += 5.0;
186 break;
187 case 'Y':
188 Yrot -= 5.0;
189 break;
190 case 27:
191 CleanUp();
192 break;
193 }
194 glutPostRedisplay();
195 }
196
197
198 static void
199 CheckExtensions(void)
200 {
201 const char *req[] = {
202 "GL_EXT_framebuffer_object",
203 "GL_ARB_draw_buffers",
204 "GL_EXT_draw_buffers2"
205 };
206
207 const char *version = (const char *) glGetString(GL_VERSION);
208 GLint numBuf;
209 GLint i;
210
211 for (i = 0; i < 3; i++) {
212 if (!glutExtensionSupported(req[i])) {
213 printf("Sorry, %s extension is required!\n", req[i]);
214 exit(1);
215 }
216 }
217 if (version[0] != '2') {
218 printf("Sorry, OpenGL 2.0 is required!\n");
219 exit(1);
220 }
221
222 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf);
223 printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf);
224 if (numBuf < 2) {
225 printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
226 exit(1);
227 }
228
229 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
230 }
231
232
233 static void
234 SetupRenderbuffers(void)
235 {
236 glGenFramebuffersEXT(1, &FBobject);
237 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
238
239 glGenRenderbuffersEXT(3, RBobjects);
240
241 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
242 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
243
244 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
245 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
246
247 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
248 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
249 Width, Height);
250
251 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
252 GL_RENDERBUFFER_EXT, RBobjects[0]);
253 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
254 GL_RENDERBUFFER_EXT, RBobjects[1]);
255 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
256 GL_RENDERBUFFER_EXT, RBobjects[2]);
257
258 CheckError(__LINE__);
259 }
260
261
262 static GLuint
263 LoadAndCompileShader(GLenum target, const char *text)
264 {
265 GLint stat;
266 GLuint shader = glCreateShader_func(target);
267 glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
268 glCompileShader_func(shader);
269 glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
270 if (!stat) {
271 GLchar log[1000];
272 GLsizei len;
273 glGetShaderInfoLog_func(shader, 1000, &len, log);
274 fprintf(stderr, "drawbuffers: problem compiling shader:\n%s\n", log);
275 exit(1);
276 }
277 return shader;
278 }
279
280
281 static void
282 CheckLink(GLuint prog)
283 {
284 GLint stat;
285 glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
286 if (!stat) {
287 GLchar log[1000];
288 GLsizei len;
289 glGetProgramInfoLog_func(prog, 1000, &len, log);
290 fprintf(stderr, "drawbuffers: shader link error:\n%s\n", log);
291 }
292 }
293
294
295 static void
296 SetupShaders(void)
297 {
298 /* emit same color to both draw buffers */
299 static const char *fragShaderText =
300 "void main() {\n"
301 " gl_FragData[0] = gl_Color; \n"
302 " gl_FragData[1] = gl_Color; \n"
303 "}\n";
304
305 GLuint fragShader;
306
307 fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
308 Program = glCreateProgram_func();
309
310 glAttachShader_func(Program, fragShader);
311 glLinkProgram_func(Program);
312 CheckLink(Program);
313 glUseProgram_func(Program);
314 }
315
316
317 static void
318 SetupLighting(void)
319 {
320 static const GLfloat ambient[4] = { 0.0, 0.0, 0.0, 0.0 };
321 static const GLfloat diffuse[4] = { 1.0, 1.0, 1.0, 0.75 };
322
323 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
324 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
325 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
326
327 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
328 glEnable(GL_LIGHT0);
329 glEnable(GL_LIGHTING);
330 }
331
332
333 static void
334 Init(void)
335 {
336 CheckExtensions();
337 GetExtensionFuncs();
338 SetupRenderbuffers();
339 SetupShaders();
340 SetupLighting();
341 glEnable(GL_DEPTH_TEST);
342
343 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
344 glEnableIndexedEXT(GL_BLEND, 1);
345 }
346
347
348 int
349 main(int argc, char *argv[])
350 {
351 glutInit(&argc, argv);
352 glutInitWindowPosition(0, 0);
353 glutInitWindowSize(Width, Height);
354 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
355 Win = glutCreateWindow(argv[0]);
356 glewInit();
357 glutIdleFunc(Anim ? Idle : NULL);
358 glutReshapeFunc(Reshape);
359 glutKeyboardFunc(Key);
360 glutDisplayFunc(Display);
361 Init();
362 glutMainLoop();
363 return 0;
364 }