--- /dev/null
+/**
+ * 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;
+}