1/**
2 * Test glFramebufferBlit()
3 * Brian Paul
4 * 27 Oct 2009
5 */
6
7#include <assert.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <math.h>
12#include <GL/glew.h>
13#include "glut_wrap.h"
14
15
16static int Win;
17static int WinWidth = 1100, WinHeight = 600;
18
19static int SrcWidth = 512, SrcHeight = 512;
20static int DstWidth = 512, DstHeight = 512;
21
22static GLuint SrcFB, DstFB;
23static GLuint SrcTex, DstTex;
24
25#if 0
26static GLenum SrcTexTarget = GL_TEXTURE_2D, SrcTexFace = GL_TEXTURE_2D;
27#else
28static GLenum SrcTexTarget = GL_TEXTURE_CUBE_MAP, SrcTexFace = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
29#endif
30
31static GLenum DstTexTarget = GL_TEXTURE_2D, DstTexFace = GL_TEXTURE_2D;
32
33static GLuint SrcTexLevel = 01, DstTexLevel = 0;
34
35
36static void
37Draw(void)
38{
39   GLboolean rp = GL_FALSE;
40   GLubyte *buf;
41   GLint srcWidth = SrcWidth >> SrcTexLevel;
42   GLint srcHeight = SrcHeight >> SrcTexLevel;
43   GLint dstWidth = DstWidth >> DstTexLevel;
44   GLint dstHeight = DstHeight >> DstTexLevel;
45   GLenum status;
46
47   /* clear window */
48   glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
49   glClearColor(0.5, 0.5, 0.5, 1.0);
50   glClear(GL_COLOR_BUFFER_BIT);
51
52
53   /* clear src buf */
54   glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB);
55   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
56   assert(status == GL_FRAMEBUFFER_COMPLETE_EXT);
57   glClearColor(0, 1, 0, 0);
58   glClear(GL_COLOR_BUFFER_BIT);
59
60   /* clear dst buf */
61   glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB);
62   status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
63   assert(status == GL_FRAMEBUFFER_COMPLETE_EXT);
64   glClearColor(1, 0, 0, 0);
65   glClear(GL_COLOR_BUFFER_BIT);
66
67   /* blit src -> dst */
68   glBindFramebufferEXT(GL_READ_FRAMEBUFFER, SrcFB);
69   glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, DstFB);
70   glBlitFramebufferEXT(0, 0, srcWidth, srcHeight,
71                        0, 0, dstWidth, dstHeight,
72                        GL_COLOR_BUFFER_BIT, GL_NEAREST);
73
74#if 01
75   /* read src results */
76   buf = malloc(4 * srcWidth * srcHeight);
77   memset(buf, 0x88, 4 * srcWidth * srcHeight);
78   glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB);
79   if (rp)
80      glReadPixels(0, 0, srcWidth, srcHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
81   else {
82      glBindTexture(SrcTexTarget, SrcTex);
83      glGetTexImage(SrcTexFace, SrcTexLevel, GL_RGBA, GL_UNSIGNED_BYTE, buf);
84   }
85
86   /* draw dst in window */
87   glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
88   glWindowPos2i(0, 0);
89   glDrawPixels(srcWidth, srcHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
90
91   printf("Src Pix[0] = %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);
92   free(buf);
93#endif
94
95   glFinish();
96
97   /* read dst results */
98   buf = malloc(4 * dstWidth * dstHeight);
99   memset(buf, 0x88, 4 * dstWidth * dstHeight);
100   glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB);
101   if (rp)
102      glReadPixels(0, 0, dstWidth, dstHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
103   else {
104      glBindTexture(DstTexTarget, DstTex);
105      glGetTexImage(DstTexFace, DstTexLevel, GL_RGBA, GL_UNSIGNED_BYTE, buf);
106   }
107
108   /* draw dst in window */
109   glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
110   glWindowPos2i(srcWidth + 2, 0);
111   glDrawPixels(dstWidth, dstHeight, GL_RGBA, GL_UNSIGNED_BYTE, buf);
112
113   printf("Dst Pix[0] = %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);
114   free(buf);
115
116   glFinish();
117
118   glutSwapBuffers();
119}
120
121
122static void
123Reshape(int width, int height)
124{
125   WinWidth = width;
126   WinHeight = height;
127   glViewport(0, 0, width, height);
128   glMatrixMode(GL_PROJECTION);
129   glLoadIdentity();
130   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
131   glMatrixMode(GL_MODELVIEW);
132   glLoadIdentity();
133   glTranslatef(0.0, 0.0, -15.0);
134}
135
136
137static void
138Key(unsigned char key, int x, int y)
139{
140   (void) x;
141   (void) y;
142   switch (key) {
143   case 27:
144      glutDestroyWindow(Win);
145      exit(0);
146      break;
147   }
148   glutPostRedisplay();
149}
150
151
152static void
153SpecialKey(int key, int x, int y)
154{
155   (void) x;
156   (void) y;
157   switch (key) {
158   }
159   glutPostRedisplay();
160}
161
162
163static void
164InitFBOs(void)
165{
166   GLuint w, h, lvl;
167
168   /* Src */
169   glGenTextures(1, &SrcTex);
170   glBindTexture(SrcTexTarget, SrcTex);
171   w = SrcWidth;
172   h = SrcHeight;
173   lvl = 0;
174   for (lvl = 0; ; lvl++) {
175      if (SrcTexTarget == GL_TEXTURE_CUBE_MAP) {
176         GLuint f;
177         for (f = 0; f < 6; f++) {
178            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, lvl, GL_RGBA8,
179                         w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
180         }
181      }
182      else {
183         /* single face */
184         glTexImage2D(SrcTexFace, lvl, GL_RGBA8, w, h, 0,
185                      GL_RGBA, GL_UNSIGNED_BYTE, NULL);
186      }
187      if (w == 1 && h == 1)
188         break;
189      if (w > 1)
190         w /= 2;
191      if (h > 1)
192         h /= 2;
193   }
194
195   glGenFramebuffersEXT(1, &SrcFB);
196   glBindFramebufferEXT(GL_FRAMEBUFFER, SrcFB);
197   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
198                             SrcTexFace, SrcTex, SrcTexLevel);
199
200   /* Dst */
201   glGenTextures(1, &DstTex);
202   glBindTexture(DstTexTarget, DstTex);
203   w = DstWidth;
204   h = DstHeight;
205   lvl = 0;
206   for (lvl = 0; ; lvl++) {
207      glTexImage2D(DstTexFace, lvl, GL_RGBA8, w, h, 0,
208                   GL_RGBA, GL_UNSIGNED_BYTE, NULL);
209      if (w == 1 && h == 1)
210         break;
211      if (w > 1)
212         w /= 2;
213      if (h > 1)
214         h /= 2;
215   }
216
217   glGenFramebuffersEXT(1, &DstFB);
218   glBindFramebufferEXT(GL_FRAMEBUFFER, DstFB);
219   glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
220                             DstTexFace, DstTex, DstTexLevel);
221}
222
223
224static void
225Init(void)
226{
227   if (!glutExtensionSupported("GL_EXT_framebuffer_object")) {
228      fprintf(stderr, "This test requires GL_EXT_framebuffer_object\n");
229      exit(1);
230   }
231
232   if (!glutExtensionSupported("GL_EXT_framebuffer_blit")) {
233      fprintf(stderr, "This test requires GL_EXT_framebuffer_blit,\n");
234      exit(1);
235   }
236
237   InitFBOs();
238
239   printf("Left rect = src FBO, Right rect = dst FBO.\n");
240   printf("Both should be green.\n");
241}
242
243
244int
245main(int argc, char *argv[])
246{
247   glutInit(&argc, argv);
248   glutInitWindowSize(WinWidth, WinHeight);
249   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
250   Win = glutCreateWindow(argv[0]);
251   glewInit();
252   glutReshapeFunc(Reshape);
253   glutKeyboardFunc(Key);
254   glutSpecialFunc(SpecialKey);
255   glutDisplayFunc(Draw);
256   Init();
257   glutMainLoop();
258   return 0;
259}
260