/* * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * author: Jerome Glisse */ #define MAXFRAME 5 #define PFINISH 1 #define MAX_PARTICLES 256 #include #include #include #include #include #define GL_GLEXT_PROTOTYPES #include #include static GLuint win_width = 1024; static GLuint win_height = 1024; static GLuint fbo; static GLuint renderbuffers[3]; static GLuint nrenderbuffers = 0; GLuint generate_simple_fbo(unsigned width, unsigned height) { GLuint fb; GLenum status; unsigned color, stencil, depth, packed; color = stencil = depth = packed = 1; #if 0 /* texture */ glGenTextures(1, &gears_tex); glBindTexture(GL_TEXTURE_2D, gears_tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #endif glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); if (color) { #if 1 glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); nrenderbuffers++; #else glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gears_tex, 0); #endif } if (stencil) { const GLenum format = (packed) ? GL_DEPTH24_STENCIL8 : GL_STENCIL_INDEX8; const GLenum attachment = (packed) ? GL_DEPTH_STENCIL_ATTACHMENT : GL_STENCIL_ATTACHMENT; glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); nrenderbuffers++; } if (!packed && depth) { glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]); glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]); nrenderbuffers++; } status = glGetError(); if (status != GL_NO_ERROR) { fprintf(stderr, "Unexpected GL error: 0x%x\n", status); exit(1); } /* All of the possible combinations that we can generate are required * to be supported by all OpenGL 3.0 implementations, with one * exception. As far as I can tell, implementations are not required * to support separate depth and stencil. That one option is handled * specially. */ status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE && !(status == GL_FRAMEBUFFER_UNSUPPORTED && stencil && !packed)) { fprintf(stderr, "Framebuffer %s color, %s stencil (%s) was not " "complete: 0x%04x\n", color ? "with" : "without", stencil ? "with" : "without", packed ? "packed" : "separate", status); exit(1); } if (status == GL_FRAMEBUFFER_UNSUPPORTED) { glDeleteRenderbuffers(nrenderbuffers, renderbuffers); glDeleteFramebuffers(1, &fb); fprintf(stderr, "Unsupported framebuffer\n"); exit(1); } glBindFramebuffer(GL_FRAMEBUFFER, 0); #if 0 glClearColor(0.2, 0.4, 0.6, 1.0); glClearDepth(0.5); glClearStencil(0x7a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glFinish(); #endif return fb; } void vsimple_probe(void) { GLfloat *pixels = malloc(256*256*sizeof(float)); glReadPixels(0, 0, 256, 256, GL_DEPTH_COMPONENT, GL_FLOAT, pixels); fprintf(stderr, "probed %f\n", pixels[100]); free(pixels); } static void draw(void) { static const float first[4] = { 0.5, 1.0, 1.0, 1.0 }; static const float second[4] = { 0.8, 0.0, 0.0, 0.0 }; #if PFINISH fprintf(stderr, "EE CLEAR 0.5 -------------------------------------------------\n"); #endif glBindFramebuffer(GL_FRAMEBUFFER, fbo); glClearColor(0.2, 0.4, 0.6, 1.0); glClearDepth(0.5); glClearStencil(0x7a); glClearBufferfv(GL_DEPTH, 0, first); #if PFINISH glFinish(); fprintf(stderr, "EE CLEAR 0.5 _________________________________________________\n"); #endif #if PFINISH fprintf(stderr, "EE CLEAR PROBE -----------------------------------------------\n"); #endif vsimple_probe(); #if PFINISH fprintf(stderr, "EE CLEAR PROBE _______________________________________________\n"); #endif #if PFINISH fprintf(stderr, "EE CLEAR 0.8 -------------------------------------------------\n"); #endif glBindFramebuffer(GL_FRAMEBUFFER, fbo); glClearColor(0.2, 0.4, 0.6, 1.0); glClearDepth(0.8); glClearStencil(0x7a); glClearBufferfv(GL_DEPTH, 0, second); #if PFINISH glFinish(); fprintf(stderr, "EE CLEAR 0.8 _________________________________________________\n"); #endif #if PFINISH fprintf(stderr, "EE CLEAR PROBE -----------------------------------------------\n"); #endif vsimple_probe(); #if PFINISH fprintf(stderr, "EE CLEAR PROBE _______________________________________________\n"); #endif exit(0); } static void idle(void) { } /* new window size or exposure */ static void reshape(int width, int height) { GLfloat h = (GLfloat) height / (GLfloat) width; glViewport(0, 0, (GLint) width, (GLint) height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -40.0); win_width = width; win_height = height; } static void init(void) { fbo = generate_simple_fbo(512, 512); } static void key(unsigned char k, int x, int y) { switch (k) { case 27: /* Escape */ exit(0); break; default: return; } glutPostRedisplay(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL); glutInitWindowSize(win_width, win_height); glutCreateWindow("glgears"); GLenum err = glewInit(); if (GLEW_OK != err) { fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); return -1; } glutKeyboardFunc(key); glutIdleFunc(idle); glutReshapeFunc(reshape); glutDisplayFunc(draw); init(); reshape(win_width, win_height); glutMainLoop(); return 0; }