summaryrefslogtreecommitdiff
path: root/progs/tests/drawbuffers2.c
diff options
context:
space:
mode:
Diffstat (limited to 'progs/tests/drawbuffers2.c')
-rw-r--r--progs/tests/drawbuffers2.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/progs/tests/drawbuffers2.c b/progs/tests/drawbuffers2.c
new file mode 100644
index 00000000000..7b8cc5ca6a3
--- /dev/null
+++ b/progs/tests/drawbuffers2.c
@@ -0,0 +1,364 @@
+/*
+ * Test GL_ARB_draw_buffers2, GL_ARB_draw_buffers, GL_EXT_framebuffer_object
+ * and GLSL's gl_FragData[].
+ *
+ * We draw to two color buffers and show the left half of the first
+ * color buffer on the left side of the window, and show the right
+ * half of the second color buffer on the right side of the window.
+ *
+ * Different color masks are used for the two color buffers.
+ * Blending is enabled for the second buffer only.
+ *
+ * Brian Paul
+ * 31 Dec 2009
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <GL/glew.h>
+#include <GL/glut.h>
+#include "extfuncs.h"
+
+static int Win;
+static int Width = 400, Height = 400;
+static GLuint FBobject, RBobjects[3];
+static GLfloat Xrot = 0.0, Yrot = 0.0;
+static GLuint Program;
+static GLboolean Anim = GL_TRUE;
+
+
+static void
+CheckError(int line)
+{
+ GLenum err = glGetError();
+ if (err) {
+ printf("GL Error 0x%x at line %d\n", (int) err, line);
+ }
+}
+
+
+static void
+Display(void)
+{
+ GLubyte *buffer = malloc(Width * Height * 4);
+ static const GLenum buffers[2] = {
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_COLOR_ATTACHMENT1_EXT
+ };
+
+ glUseProgram_func(Program);
+
+ glEnable(GL_DEPTH_TEST);
+
+ /* draw to user framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
+
+ /* Clear color buffer 0 (blue) */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /* Clear color buffer 1 (1 - blue) */
+ glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ /* draw to two buffers w/ fragment shader */
+ glDrawBuffersARB(2, buffers);
+
+ /* different color masks for each buffer */
+ if (1) {
+ glColorMaskIndexedEXT(0, GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glColorMaskIndexedEXT(1, GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
+ }
+
+ glPushMatrix();
+ glRotatef(Xrot, 1, 0, 0);
+ glRotatef(Yrot, 0, 1, 0);
+ glPushMatrix();
+ glTranslatef(1, 0, 0);
+ glutSolidTorus(1.0, 2.0, 10, 20);
+ glPopMatrix();
+ glPushMatrix();
+ glTranslatef(-1, 0, 0);
+ glRotatef(90, 1, 0, 0);
+ glutSolidTorus(1.0, 2.0, 10, 20);
+ glPopMatrix();
+ glPopMatrix();
+
+ /* restore default color masks */
+ glColorMaskIndexedEXT(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glColorMaskIndexedEXT(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ /* read from user framebuffer */
+ /* left half = colorbuffer 0 */
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glPixelStorei(GL_PACK_ROW_LENGTH, Width);
+ glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+ glReadPixels(0, 0, Width / 2, Height, GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer);
+
+ /* right half = colorbuffer 1 */
+ glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glPixelStorei(GL_PACK_SKIP_PIXELS, Width / 2);
+ glReadPixels(Width / 2, 0, Width - Width / 2, Height,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ buffer);
+
+ /* draw to window */
+ glUseProgram_func(0);
+ glDisable(GL_DEPTH_TEST);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glWindowPos2iARB(0, 0);
+ glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ free(buffer);
+ glutSwapBuffers();
+ CheckError(__LINE__);
+}
+
+
+static void
+Idle(void)
+{
+ Xrot = glutGet(GLUT_ELAPSED_TIME) * 0.05;
+ glutPostRedisplay();
+}
+
+
+static void
+Reshape(int width, int height)
+{
+ float ar = (float) width / (float) height;
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 35.0);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -20.0);
+
+ Width = width;
+ Height = height;
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+ Width, Height);
+}
+
+
+static void
+CleanUp(void)
+{
+ glDeleteFramebuffersEXT(1, &FBobject);
+ glDeleteRenderbuffersEXT(3, RBobjects);
+ glutDestroyWindow(Win);
+ exit(0);
+}
+
+
+static void
+Key(unsigned char key, int x, int y)
+{
+ (void) x;
+ (void) y;
+ switch (key) {
+ case ' ':
+ Anim = !Anim;
+ glutIdleFunc(Anim ? Idle : NULL);
+ break;
+ case 'x':
+ Xrot += 5.0;
+ break;
+ case 'X':
+ Xrot -= 5.0;
+ break;
+ case 'y':
+ Yrot += 5.0;
+ break;
+ case 'Y':
+ Yrot -= 5.0;
+ break;
+ case 27:
+ CleanUp();
+ break;
+ }
+ glutPostRedisplay();
+}
+
+
+static void
+CheckExtensions(void)
+{
+ const char *req[] = {
+ "GL_EXT_framebuffer_object",
+ "GL_ARB_draw_buffers",
+ "GL_EXT_draw_buffers2"
+ };
+
+ const char *version = (const char *) glGetString(GL_VERSION);
+ GLint numBuf;
+ GLint i;
+
+ for (i = 0; i < 3; i++) {
+ if (!glutExtensionSupported(req[i])) {
+ printf("Sorry, %s extension is required!\n", req[i]);
+ exit(1);
+ }
+ }
+ if (version[0] != '2') {
+ printf("Sorry, OpenGL 2.0 is required!\n");
+ exit(1);
+ }
+
+ glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &numBuf);
+ printf("GL_MAX_DRAW_BUFFERS_ARB = %d\n", numBuf);
+ if (numBuf < 2) {
+ printf("Sorry, GL_MAX_DRAW_BUFFERS_ARB needs to be >= 2\n");
+ exit(1);
+ }
+
+ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
+}
+
+
+static void
+SetupRenderbuffers(void)
+{
+ glGenFramebuffersEXT(1, &FBobject);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBobject);
+
+ glGenRenderbuffersEXT(3, RBobjects);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGB, Width, Height);
+
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RBobjects[2]);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+ Width, Height);
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[0]);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[1]);
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, RBobjects[2]);
+
+ CheckError(__LINE__);
+}
+
+
+static GLuint
+LoadAndCompileShader(GLenum target, const char *text)
+{
+ GLint stat;
+ GLuint shader = glCreateShader_func(target);
+ glShaderSource_func(shader, 1, (const GLchar **) &text, NULL);
+ glCompileShader_func(shader);
+ glGetShaderiv_func(shader, GL_COMPILE_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetShaderInfoLog_func(shader, 1000, &len, log);
+ fprintf(stderr, "drawbuffers: problem compiling shader:\n%s\n", log);
+ exit(1);
+ }
+ return shader;
+}
+
+
+static void
+CheckLink(GLuint prog)
+{
+ GLint stat;
+ glGetProgramiv_func(prog, GL_LINK_STATUS, &stat);
+ if (!stat) {
+ GLchar log[1000];
+ GLsizei len;
+ glGetProgramInfoLog_func(prog, 1000, &len, log);
+ fprintf(stderr, "drawbuffers: shader link error:\n%s\n", log);
+ }
+}
+
+
+static void
+SetupShaders(void)
+{
+ /* emit same color to both draw buffers */
+ static const char *fragShaderText =
+ "void main() {\n"
+ " gl_FragData[0] = gl_Color; \n"
+ " gl_FragData[1] = gl_Color; \n"
+ "}\n";
+
+ GLuint fragShader;
+
+ fragShader = LoadAndCompileShader(GL_FRAGMENT_SHADER, fragShaderText);
+ Program = glCreateProgram_func();
+
+ glAttachShader_func(Program, fragShader);
+ glLinkProgram_func(Program);
+ CheckLink(Program);
+ glUseProgram_func(Program);
+}
+
+
+static void
+SetupLighting(void)
+{
+ static const GLfloat ambient[4] = { 0.0, 0.0, 0.0, 0.0 };
+ static const GLfloat diffuse[4] = { 1.0, 1.0, 1.0, 0.75 };
+
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse);
+
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHTING);
+}
+
+
+static void
+Init(void)
+{
+ CheckExtensions();
+ GetExtensionFuncs();
+ SetupRenderbuffers();
+ SetupShaders();
+ SetupLighting();
+ glEnable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnableIndexedEXT(GL_BLEND, 1);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitWindowPosition(0, 0);
+ glutInitWindowSize(Width, Height);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
+ Win = glutCreateWindow(argv[0]);
+ glewInit();
+ glutIdleFunc(Anim ? Idle : NULL);
+ glutReshapeFunc(Reshape);
+ glutKeyboardFunc(Key);
+ glutDisplayFunc(Display);
+ Init();
+ glutMainLoop();
+ return 0;
+}