8 #if defined(unix) || defined(__unix__)
12 #define get_proc_addr(s) (void (*)())glXGetProcAddress((unsigned char*)(s))
24 static const char *modestr[] = { "GL_POINTS", "glDrawPixels", "textured quad",
30 void reshape(int x, int y);
31 void keyb(unsigned char key, int x, int y);
32 void change_mode(int m);
34 int win_width, win_height;
35 int max_xscroll, max_yscroll;
39 unsigned int img[IMG_W * IMG_H];
41 unsigned int vbo_pos, vbo_col;
43 unsigned int tex, quad, tri;
45 int mode = MODE_POINTS;
49 unsigned int start_tm;
50 unsigned int num_frames;
52 void (*gl_gen_buffers)(GLsizei, GLuint*);
53 void (*gl_bind_buffer)(GLenum, GLuint);
54 void (*gl_buffer_data)(GLenum, GLsizeiptr, const void*, GLenum);
55 void (*gl_buffer_sub_data)(GLenum, GLintptr, GLsizeiptr, const void *data);
61 static void (*glx_swap_interval_ext)(Display*, Window, int);
62 static void (*glx_swap_interval_mesa)(int);
63 static void (*glx_swap_interval_sgi)(int);
67 int main(int argc, char **argv)
69 glutInit(&argc, argv);
70 glutInitWindowSize(800, 600);
71 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
72 glutCreateWindow("GL pixel drawing methods");
76 glutDisplayFunc(display);
77 glutReshapeFunc(reshape);
78 glutKeyboardFunc(keyb);
85 start_tm = glutGet(GLUT_ELAPSED_TIME);
93 int i, j, xor, r, g, b;
98 extstr = (char*)glGetString(GL_EXTENSIONS);
100 if(strstr(extstr, "ARB_vertex_buffer_object")) {
101 if(!(gl_gen_buffers = get_proc_addr("glGenBuffers"))) {
102 gl_gen_buffers = get_proc_addr("glGenBuffersARB");
104 if(!(gl_bind_buffer = get_proc_addr("glBindBuffer"))) {
105 gl_bind_buffer = get_proc_addr("glBindBufferARB");
107 if(!(gl_buffer_data = get_proc_addr("glBufferData"))) {
108 gl_buffer_data = get_proc_addr("glBufferDataARB");
110 if(!(gl_buffer_sub_data = get_proc_addr("glBufferSubData"))) {
111 gl_buffer_sub_data = get_proc_addr("glBufferSubDataARB");
113 if(gl_gen_buffers && gl_bind_buffer && gl_buffer_data && gl_buffer_sub_data) {
118 printf("Using vertex buffer objects for the GL_POINTS test\n");
120 printf("No VBO extension, using client-side vertex arrays for the GL_POINTS test\n");
126 XWindowAttributes wattr;
128 dpy = glXGetCurrentDisplay();
129 win = glXGetCurrentDrawable();
131 XGetWindowAttributes(dpy, win, &wattr);
132 scr = XScreenNumberOfScreen(wattr.screen);
134 if(!(extstr = glXQueryExtensionsString(dpy, scr))) {
139 if(strstr(extstr, "GLX_EXT_swap_control") && (glx_swap_interval_ext = get_proc_addr("glXSwapIntervalEXT"))) {
140 printf("using GLX_EXT_swap_control to disable vsync\n");
141 glx_swap_interval_ext(dpy, win, 0);
142 } else if(strstr(extstr, "GLX_MESA_swap_control") && (glx_swap_interval_mesa = get_proc_addr("glXSwapIntervalMESA"))) {
143 printf("using GLX_MESA_swap_control to disable vsync\n");
144 glx_swap_interval_mesa(0);
145 } else if(strstr(extstr, "GLX_SGI_swap_control") && (glx_swap_interval_sgi = get_proc_addr("glXSwapIntervalSGI"))) {
146 printf("using GLX_SGI_swap_control to disable vsync\n");
147 glx_swap_interval_sgi(0);
149 fprintf(stderr, "No vsync extension found, you might need to disable vsync externally\n");
155 for(i=0; i<IMG_H; i++) {
156 for(j=0; j<IMG_W; j++) {
158 r = (xor >> 1) & 0xff;
160 b = (xor << 1) & 0xff;
161 *ptr++ = r | (g << 8) | (b << 16);
165 glPixelStorei(GL_UNPACK_ROW_LENGTH, IMG_W);
167 win_width = glutGet(GLUT_WINDOW_WIDTH);
168 win_height = glutGet(GLUT_WINDOW_HEIGHT);
170 glGenTextures(1, &tex);
171 glBindTexture(GL_TEXTURE_2D, tex);
172 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
173 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
174 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win_width, win_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
176 varr_sz = win_width * win_height * sizeof *varr * 2;
177 if(!(varr = malloc(varr_sz))) {
178 fprintf(stderr, "failed to allocate vertex array\n");
181 carr_sz = win_width * win_height * sizeof *carr * 3;
182 if(!(carr = malloc(carr_sz))) {
183 fprintf(stderr, "failed to allocate color array\n");
188 for(i=0; i<win_height; i++) {
189 for(j=0; j<win_width; j++) {
197 gl_gen_buffers(1, &vbo_pos);
198 gl_bind_buffer(GL_ARRAY_BUFFER, vbo_pos);
199 gl_buffer_data(GL_ARRAY_BUFFER, varr_sz, varr, GL_STATIC_DRAW);
201 gl_gen_buffers(1, &vbo_col);
202 gl_bind_buffer(GL_ARRAY_BUFFER, vbo_col);
203 gl_buffer_data(GL_ARRAY_BUFFER, carr_sz, 0, GL_STREAM_DRAW);
206 quad = glGenLists(1);
207 glNewList(quad, GL_COMPILE);
209 glTexCoord2f(0, 0); glVertex2f(0, 0);
210 glTexCoord2f(1, 0); glVertex2f(1, 0);
211 glTexCoord2f(1, 1); glVertex2f(1, 1);
212 glTexCoord2f(0, 1); glVertex2f(0, 1);
217 glNewList(tri, GL_COMPILE);
218 glBegin(GL_TRIANGLES);
219 glTexCoord2f(0, 0); glVertex2f(0, 0);
220 glTexCoord2f(2, 0); glVertex2f(2, 0);
221 glTexCoord2f(0, 2); glVertex2f(0, 2);
231 unsigned int tm = glutGet(GLUT_ELAPSED_TIME);
233 float t = tm / 256.0f;
234 int xoffs = (int)((sin(t) * 0.5f + 0.5f) * max_xscroll);
235 int yoffs = (int)((cos(t) * 0.5f + 0.5f) * max_yscroll);
236 unsigned int *start = img + yoffs * IMG_W + xoffs;
239 glMatrixMode(GL_MODELVIEW);
244 /* draw with points */
246 for(i=0; i<win_height; i++) {
247 for(j=0; j<win_width; j++) {
248 int r = start[j] & 0xff;
249 int g = (start[j] >> 8) & 0xff;
250 int b = (start[j] >> 16) & 0xff;
251 vptr[0] = r / 255.0f;
252 vptr[1] = g / 255.0f;
253 vptr[2] = b / 255.0f;
260 gl_bind_buffer(GL_ARRAY_BUFFER, vbo_pos);
261 glVertexPointer(2, GL_FLOAT, 0, 0);
262 gl_bind_buffer(GL_ARRAY_BUFFER, vbo_col);
263 gl_buffer_sub_data(GL_ARRAY_BUFFER, 0, carr_sz, carr);
264 glColorPointer(3, GL_FLOAT, 0, 0);
265 gl_bind_buffer(GL_ARRAY_BUFFER, 0);
267 glVertexPointer(2, GL_FLOAT, 0, varr);
268 glColorPointer(3, GL_FLOAT, 0, carr);
271 glEnableClientState(GL_VERTEX_ARRAY);
272 glEnableClientState(GL_COLOR_ARRAY);
274 glDrawArrays(GL_POINTS, 0, win_width * win_height);
276 glDisableClientState(GL_VERTEX_ARRAY);
277 glDisableClientState(GL_COLOR_ARRAY);
281 /* draw with glDrawPixels */
282 glDrawPixels(win_width, win_height, GL_RGBA, GL_UNSIGNED_BYTE, start);
287 /* draw with textured quad or triangle */
288 glBindTexture(GL_TEXTURE_2D, tex);
289 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, win_width, win_height, GL_RGBA,
290 GL_UNSIGNED_BYTE, start);
291 glEnable(GL_TEXTURE_2D);
292 glScalef(win_width, win_height, 1);
293 glCallList(mode == MODE_TEXQUAD ? quad : tri);
294 glDisable(GL_TEXTURE_2D);
299 assert(glGetError() == GL_NO_ERROR);
302 tm = glutGet(GLUT_ELAPSED_TIME);
303 interv = tm - start_tm;
305 unsigned int fps = 100000 * num_frames / interv;
306 printf("%s: %.2f fps\n", modestr[mode], fps / 100.0f);
310 if(mode < NUM_MODES - 1) {
311 change_mode(mode + 1);
323 void reshape(int x, int y)
325 glViewport(0, 0, x, y);
327 glMatrixMode(GL_PROJECTION);
329 glOrtho(0, x, 0, y, -1, 1);
333 max_xscroll = IMG_W - win_width;
334 max_yscroll = IMG_H - win_height;
335 if(max_xscroll < 0) max_xscroll = 0;
336 if(max_yscroll < 0) max_yscroll = 0;
339 void keyb(unsigned char key, int x, int y)
346 change_mode((mode + 1) % NUM_MODES);
354 void change_mode(int m)
358 sprintf(title, "GL pixel drawing test: %s\n", modestr[mode]);
359 glutSetWindowTitle(title);