done
[glpixels] / glpixels.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <assert.h>
5 #define GL_GLEXT_PROTOTYPES     1
6 #include <GL/glut.h>
7
8 enum {
9         MODE_POINTS,
10         MODE_DRAWPIX,
11         MODE_TEXQUAD,
12         MODE_TEXTRI,
13
14         NUM_MODES
15 };
16
17 static const char *modestr[] = { "GL_POINTS", "glDrawPixels", "textured quad",
18         "textured triangle"};
19
20 int init(void);
21 void display(void);
22 void idle(void);
23 void reshape(int x, int y);
24 void keyb(unsigned char key, int x, int y);
25 void change_mode(int m);
26
27 int win_width, win_height;
28 int max_xscroll, max_yscroll;
29
30 #define IMG_W   1024
31 #define IMG_H   1024
32 unsigned int img[IMG_W * IMG_H];
33 float *varr, *carr;
34 unsigned int vbo_pos, vbo_col;
35 int varr_sz, carr_sz;
36 unsigned int tex, quad, tri;
37
38 int mode = MODE_POINTS;
39
40 int have_vbo = 1;       /* TODO */
41
42 unsigned int start_tm;
43 unsigned int num_frames;
44
45
46 int main(int argc, char **argv)
47 {
48         glutInit(&argc, argv);
49         glutInitWindowSize(800, 600);
50         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
51         glutCreateWindow("GL pixel drawing methods");
52
53         change_mode(mode);
54
55         glutDisplayFunc(display);
56         glutReshapeFunc(reshape);
57         glutKeyboardFunc(keyb);
58         glutIdleFunc(idle);
59
60         if(init() == -1) {
61                 return 1;
62         }
63
64         start_tm = glutGet(GLUT_ELAPSED_TIME);
65         glutMainLoop();
66         return 0;
67 }
68
69
70 int init(void)
71 {
72         int i, j, xor, r, g, b;
73         unsigned int *ptr;
74         float *vptr;
75
76         ptr = img;
77         for(i=0; i<IMG_H; i++) {
78                 for(j=0; j<IMG_W; j++) {
79                         xor = i ^ j;
80                         r = (xor >> 1) & 0xff;
81                         g = xor & 0xff;
82                         b = (xor << 1) & 0xff;
83                         *ptr++ = r | (g << 8) | (b << 16);
84                 }
85         }
86
87         glPixelStorei(GL_UNPACK_ROW_LENGTH, IMG_W);
88
89         win_width = glutGet(GLUT_WINDOW_WIDTH);
90         win_height = glutGet(GLUT_WINDOW_HEIGHT);
91
92         glGenTextures(1, &tex);
93         glBindTexture(GL_TEXTURE_2D, tex);
94         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
95         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
96         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
97
98         varr_sz = win_width * win_height * sizeof *varr * 2;
99         if(!(varr = malloc(varr_sz))) {
100                 fprintf(stderr, "failed to allocate vertex array\n");
101                 return -1;
102         }
103         carr_sz = win_width * win_height * sizeof *carr * 3;
104         if(!(carr = malloc(carr_sz))) {
105                 fprintf(stderr, "failed to allocate color array\n");
106                 return -1;
107         }
108
109         vptr = varr;
110         for(i=0; i<win_height; i++) {
111                 for(j=0; j<win_width; j++) {
112                         vptr[0] = j;
113                         vptr[1] = i;
114                         vptr += 2;
115                 }
116         }
117
118         if(have_vbo) {
119                 glGenBuffers(1, &vbo_pos);
120                 glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
121                 glBufferData(GL_ARRAY_BUFFER, varr_sz, varr, GL_STATIC_DRAW);
122
123                 glGenBuffers(1, &vbo_col);
124                 glBindBuffer(GL_ARRAY_BUFFER, vbo_col);
125                 glBufferData(GL_ARRAY_BUFFER, carr_sz, 0, GL_STREAM_DRAW);
126         }
127
128         quad = glGenLists(1);
129         glNewList(quad, GL_COMPILE);
130         glBegin(GL_QUADS);
131         glTexCoord2f(0, 0); glVertex2f(0, 0);
132         glTexCoord2f(1, 0); glVertex2f(1, 0);
133         glTexCoord2f(1, 1); glVertex2f(1, 1);
134         glTexCoord2f(0, 1); glVertex2f(0, 1);
135         glEnd();
136         glEndList();
137
138         tri = glGenLists(1);
139         glNewList(tri, GL_COMPILE);
140         glBegin(GL_TRIANGLES);
141         glTexCoord2f(0, 0); glVertex2f(0, 0);
142         glTexCoord2f(2, 0); glVertex2f(2, 0);
143         glTexCoord2f(0, 2); glVertex2f(0, 2);
144         glEnd();
145         glEndList();
146
147         return 0;
148 }
149
150 void display(void)
151 {
152         int i, j;
153         unsigned int tm = glutGet(GLUT_ELAPSED_TIME);
154         unsigned int interv;
155         float t = tm / 256.0f;
156         int xoffs = (int)((sin(t) * 0.5f + 0.5f) * max_xscroll);
157         int yoffs = (int)((cos(t) * 0.5f + 0.5f) * max_yscroll);
158         unsigned int *start = img + yoffs * IMG_W + xoffs;
159         float *vptr = varr;
160
161         glMatrixMode(GL_MODELVIEW);
162         glLoadIdentity();
163
164         switch(mode) {
165         case MODE_POINTS:
166                 /* draw with points */
167                 vptr = carr;
168                 for(i=0; i<win_height; i++) {
169                         for(j=0; j<win_width; j++) {
170                                 int r = start[j] & 0xff;
171                                 int g = (start[j] >> 8) & 0xff;
172                                 int b = (start[j] >> 16) & 0xff;
173                                 vptr[0] = r / 255.0f;
174                                 vptr[1] = g / 255.0f;
175                                 vptr[2] = b / 255.0f;
176                                 vptr += 3;
177                         }
178                         start += IMG_W;
179                 }
180
181                 if(have_vbo) {
182                         glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
183                         glVertexPointer(2, GL_FLOAT, 0, 0);
184                         glBindBuffer(GL_ARRAY_BUFFER, vbo_col);
185                         glBufferSubData(GL_ARRAY_BUFFER, 0, carr_sz, carr);
186                         glColorPointer(3, GL_FLOAT, 0, 0);
187                         glBindBuffer(GL_ARRAY_BUFFER, 0);
188                 } else {
189                         glVertexPointer(2, GL_FLOAT, 0, varr);
190                         glColorPointer(3, GL_FLOAT, 0, carr);
191                 }
192
193                 glEnableClientState(GL_VERTEX_ARRAY);
194                 glEnableClientState(GL_COLOR_ARRAY);
195
196                 glDrawArrays(GL_POINTS, 0, win_width * win_height);
197
198                 glDisableClientState(GL_VERTEX_ARRAY);
199                 glDisableClientState(GL_COLOR_ARRAY);
200                 break;
201
202         case MODE_DRAWPIX:
203                 /* draw with glDrawPixels */
204                 glDrawPixels(win_width, win_height, GL_RGBA, GL_UNSIGNED_BYTE, start);
205                 break;
206
207         case MODE_TEXQUAD:
208         case MODE_TEXTRI:
209                 /* draw with textured quad or triangle */
210                 glBindTexture(GL_TEXTURE_2D, tex);
211                 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, win_width, win_height, GL_RGBA,
212                                 GL_UNSIGNED_BYTE, start);
213                 glEnable(GL_TEXTURE_2D);
214                 glScalef(win_width, win_height, 1);
215                 glCallList(mode == MODE_TEXQUAD ? quad : tri);
216                 glDisable(GL_TEXTURE_2D);
217                 break;
218         }
219
220         glutSwapBuffers();
221         assert(glGetError() == GL_NO_ERROR);
222
223         tm = glutGet(GLUT_ELAPSED_TIME);
224         interv = tm - start_tm;
225         if(++num_frames == 1000 || interv > 5000) {
226                 unsigned int fps = 100000 * num_frames / interv;
227                 printf("%s: %.2f fps\n", modestr[mode], fps / 100.0f);
228                 num_frames = 0;
229                 start_tm = tm;
230
231                 if(mode < NUM_MODES - 1) {
232                         change_mode(mode + 1);
233                 } else {
234                         exit(0);
235                 }
236         }
237 }
238
239 void idle(void)
240 {
241         glutPostRedisplay();
242 }
243
244 void reshape(int x, int y)
245 {
246         glViewport(0, 0, x, y);
247
248         glMatrixMode(GL_PROJECTION);
249         glLoadIdentity();
250         glOrtho(0, x, 0, y, -1, 1);
251
252         win_width = x;
253         win_height = y;
254         max_xscroll = IMG_W - win_width;
255         max_yscroll = IMG_H - win_height;
256         if(max_xscroll < 0) max_xscroll = 0;
257         if(max_yscroll < 0) max_yscroll = 0;
258 }
259
260 void keyb(unsigned char key, int x, int y)
261 {
262         switch(key) {
263         case 27:
264                 exit(0);
265
266         case ' ':
267                 change_mode((mode + 1) % NUM_MODES);
268                 break;
269
270         default:
271                 break;
272         }
273 }
274
275 void change_mode(int m)
276 {
277         char title[128];
278         mode = m;
279         sprintf(title, "GL pixel drawing test: %s\n", modestr[mode]);
280         glutSetWindowTitle(title);
281 }