| /** |
| * Test glFramebufferBlit() |
| * Brian Paul |
| * 27 Oct 2009 |
| */ |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <math.h> |
| #include <GL/glew.h> |
| #include <GL/glut.h> |
| |
| |
| static int Win; |
| static int WinWidth = 1100, WinHeight = 600; |
| |
| static int SrcWidth = 512, SrcHeight = 512; |
| static int DstWidth = 512, DstHeight = 512; |
| |
| static GLuint SrcFB, DstFB; |
| static GLuint SrcTex, DstTex; |
| |
| #if 0 |
| static GLenum SrcTexTarget = GL_TEXTURE_2D, SrcTexFace = GL_TEXTURE_2D; |
| #else |
| static GLenum SrcTexTarget = GL_TEXTURE_CUBE_MAP, SrcTexFace = GL_TEXTURE_CUBE_MAP_POSITIVE_X; |
| #endif |
| |
| static GLenum DstTexTarget = GL_TEXTURE_2D, DstTexFace = GL_TEXTURE_2D; |
| |
| static GLuint SrcTexLevel = 01, DstTexLevel = 0; |
| |
| |
| static void |
| Draw(void) |
| { |
| GLboolean rp = GL_FALSE; |
| GLubyte *buf; |
| GLint srcWidth = SrcWidth >> SrcTexLevel; |
| GLint srcHeight = SrcHeight >> SrcTexLevel; |
| GLint dstWidth = DstWidth >> DstTexLevel; |
| GLint dstHeight = DstHeight >> DstTexLevel; |
| GLenum status; |
| |
| /* clear window */ |
| glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| glClearColor(0.5, 0.5, 0.5, 1.0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| |
| /* clear src buf */ |
| glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB); |
| status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| assert(status == GL_FRAMEBUFFER_COMPLETE_EXT); |
| glClearColor(0, 1, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| /* clear dst buf */ |
| glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB); |
| status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); |
| assert(status == GL_FRAMEBUFFER_COMPLETE_EXT); |
| glClearColor(1, 0, 0, 0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| |
| /* blit src -> dst */ |
| glBindFramebufferEXT(GL_READ_FRAMEBUFFER, SrcFB); |
| glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, DstFB); |
| glBlitFramebufferEXT(0, 0, srcWidth, srcHeight, |
| 0, 0, dstWidth, dstHeight, |
| GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| |
| #if 01 |
| /* read src results */ |
| buf = malloc(4 * srcWidth * srcHeight); |
| memset(buf, 0x88, 4 * srcWidth * srcHeight); |
| glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB); |
| if (rp) |
| glReadPixels(0, 0, srcWidth, srcHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| else { |
| glBindTexture(SrcTexTarget, SrcTex); |
| glGetTexImage(SrcTexFace, SrcTexLevel, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| } |
| |
| /* draw dst in window */ |
| glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| glWindowPos2i(0, 0); |
| glDrawPixels(srcWidth, srcHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| |
| printf("Src Pix[0] = %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]); |
| free(buf); |
| #endif |
| |
| glFinish(); |
| |
| /* read dst results */ |
| buf = malloc(4 * dstWidth * dstHeight); |
| memset(buf, 0x88, 4 * dstWidth * dstHeight); |
| glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB); |
| if (rp) |
| glReadPixels(0, 0, dstWidth, dstHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| else { |
| glBindTexture(DstTexTarget, DstTex); |
| glGetTexImage(DstTexFace, DstTexLevel, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| } |
| |
| /* draw dst in window */ |
| glBindFramebufferEXT(GL_FRAMEBUFFER, 0); |
| glWindowPos2i(srcWidth + 2, 0); |
| glDrawPixels(dstWidth, dstHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
| |
| printf("Dst Pix[0] = %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]); |
| free(buf); |
| |
| glFinish(); |
| |
| glutSwapBuffers(); |
| } |
| |
| |
| static void |
| Reshape(int width, int height) |
| { |
| WinWidth = width; |
| WinHeight = height; |
| glViewport(0, 0, width, height); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); |
| glMatrixMode(GL_MODELVIEW); |
| glLoadIdentity(); |
| glTranslatef(0.0, 0.0, -15.0); |
| } |
| |
| |
| static void |
| Key(unsigned char key, int x, int y) |
| { |
| (void) x; |
| (void) y; |
| switch (key) { |
| case 27: |
| glutDestroyWindow(Win); |
| exit(0); |
| break; |
| } |
| glutPostRedisplay(); |
| } |
| |
| |
| static void |
| SpecialKey(int key, int x, int y) |
| { |
| (void) x; |
| (void) y; |
| switch (key) { |
| } |
| glutPostRedisplay(); |
| } |
| |
| |
| static void |
| InitFBOs(void) |
| { |
| GLuint w, h, lvl; |
| |
| /* Src */ |
| glGenTextures(1, &SrcTex); |
| glBindTexture(SrcTexTarget, SrcTex); |
| w = SrcWidth; |
| h = SrcHeight; |
| lvl = 0; |
| for (lvl = 0; ; lvl++) { |
| if (SrcTexTarget == GL_TEXTURE_CUBE_MAP) { |
| GLuint f; |
| for (f = 0; f < 6; f++) { |
| glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, lvl, GL_RGBA8, |
| w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| } |
| } |
| else { |
| /* single face */ |
| glTexImage2D(SrcTexFace, lvl, GL_RGBA8, w, h, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| } |
| if (w == 1 && h == 1) |
| break; |
| if (w > 1) |
| w /= 2; |
| if (h > 1) |
| h /= 2; |
| } |
| |
| glGenFramebuffersEXT(1, &SrcFB); |
| glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB); |
| glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| SrcTexFace, SrcTex, SrcTexLevel); |
| |
| /* Dst */ |
| glGenTextures(1, &DstTex); |
| glBindTexture(DstTexTarget, DstTex); |
| w = DstWidth; |
| h = DstHeight; |
| lvl = 0; |
| for (lvl = 0; ; lvl++) { |
| glTexImage2D(DstTexFace, lvl, GL_RGBA8, w, h, 0, |
| GL_RGBA, GL_UNSIGNED_BYTE, NULL); |
| if (w == 1 && h == 1) |
| break; |
| if (w > 1) |
| w /= 2; |
| if (h > 1) |
| h /= 2; |
| } |
| |
| glGenFramebuffersEXT(1, &DstFB); |
| glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB); |
| glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, |
| DstTexFace, DstTex, DstTexLevel); |
| } |
| |
| |
| static void |
| Init(void) |
| { |
| if (!glutExtensionSupported("GL_EXT_framebuffer_object")) { |
| fprintf(stderr, "This test requires GL_EXT_framebuffer_object\n"); |
| exit(1); |
| } |
| |
| if (!glutExtensionSupported("GL_EXT_framebuffer_blit")) { |
| fprintf(stderr, "This test requires GL_EXT_framebuffer_blit,\n"); |
| exit(1); |
| } |
| |
| InitFBOs(); |
| |
| printf("Left rect = src FBO, Right rect = dst FBO.\n"); |
| printf("Both should be green.\n"); |
| } |
| |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| glutInit(&argc, argv); |
| glutInitWindowSize(WinWidth, WinHeight); |
| glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); |
| Win = glutCreateWindow(argv[0]); |
| glewInit(); |
| glutReshapeFunc(Reshape); |
| glutKeyboardFunc(Key); |
| glutSpecialFunc(SpecialKey); |
| glutDisplayFunc(Draw); |
| Init(); |
| glutMainLoop(); |
| return 0; |
| } |