|
|
@@ -0,0 +1,259 @@ |
|
|
|
/** |
|
|
|
* 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; |
|
|
|
} |