260 lines
6.2 KiB
C
260 lines
6.2 KiB
C
|
/**
|
||
|
* 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;
|
||
|
}
|