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