static void redraw_handler(struct window *window, void *data) { struct gears *gears = data; draw_gears(gears); }
/** Draw single frame, do SwapBuffers, compute FPS */ static void draw_frame(Display *dpy, Window win) { static int frames = 0; static double tRot0 = -1.0, tRate0 = -1.0; double dt, t = current_time(); if (tRot0 < 0.0) tRot0 = t; dt = t - tRot0; tRot0 = t; if (animate) { /* advance rotation for next frame */ angle += 70.0 * dt; /* 70 degrees per second */ if (angle > 3600.0) angle -= 3600.0; } draw_gears(); glXSwapBuffers(dpy, win); frames++; if (tRate0 < 0.0) tRate0 = t; if (t - tRate0 >= 5.0) { GLfloat seconds = t - tRate0; GLfloat fps = frames / seconds; printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, fps); tRate0 = t; frames = 0; } }
ENTRYPOINT void draw_pinion (ModeInfo *mi) { pinion_configuration *pp = &pps[MI_SCREEN(mi)]; Display *dpy = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); Bool wire_p = MI_IS_WIREFRAME(mi); if (!pp->glx_context) return; glXMakeCurrent(MI_DISPLAY(mi), MI_WINDOW(mi), *(pp->glx_context)); if (!pp->button_down_p) { if (!debug_one_gear_p || pp->ngears == 0) scroll_gears (mi); spin_gears (mi); } glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); glEnable(GL_NORMALIZE); glEnable(GL_CULL_FACE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix (); { gltrackball_rotate (pp->trackball); mi->polygon_count = 0; glScalef (16, 16, 16); /* map vp_width/height to the screen */ if (debug_one_gear_p) /* zoom in */ glScalef (3, 3, 3); else if (debug_p) /* show the "visible" and "layout" areas */ { GLfloat ow = pp->layout_right - pp->render_left; GLfloat rw = pp->render_right - pp->render_left; GLfloat s = (pp->vp_width / ow) * 0.85; glScalef (s, s, s); glTranslatef (-(ow - rw) / 2, 0, 0); } else { GLfloat s = 1.2; glScalef (s, s, s); /* zoom in a little more */ glRotatef (-35, 1, 0, 0); /* tilt back */ glRotatef ( 8, 0, 1, 0); /* tilt left */ glTranslatef (0.02, 0.1, 0); /* pan up */ } draw_gears (mi); if (debug_p) { if (!wire_p) glDisable(GL_LIGHTING); glColor3f (0.6, 0, 0); glBegin(GL_LINE_LOOP); glVertex3f (pp->render_left, pp->vp_top, 0); glVertex3f (pp->render_right, pp->vp_top, 0); glVertex3f (pp->render_right, pp->vp_bottom, 0); glVertex3f (pp->render_left, pp->vp_bottom, 0); glEnd(); glColor3f (0.4, 0, 0); glBegin(GL_LINES); glVertex3f (pp->vp_left, pp->vp_top, 0); glVertex3f (pp->vp_left, pp->vp_bottom, 0); glVertex3f (pp->vp_right, pp->vp_top, 0); glVertex3f (pp->vp_right, pp->vp_bottom, 0); glEnd(); glColor3f (0, 0.4, 0); glBegin(GL_LINE_LOOP); glVertex3f (pp->layout_left, pp->vp_top, 0); glVertex3f (pp->layout_right, pp->vp_top, 0); glVertex3f (pp->layout_right, pp->vp_bottom, 0); glVertex3f (pp->layout_left, pp->vp_bottom, 0); glEnd(); if (!wire_p) glEnable(GL_LIGHTING); } if (pp->draw_tick++ > 10) /* only do this every N frames */ { pp->draw_tick = 0; find_mouse_gear (mi); new_label (mi); } } glPopMatrix (); glCallList (pp->title_list); if (mi->fps_p) do_fps (mi); glFinish(); glXSwapBuffers(dpy, window); }
/* Mouse hit detection */ static void find_mouse_gear (ModeInfo *mi) { pinion_configuration *pp = &pps[MI_SCREEN(mi)]; int screen_width = MI_WIDTH (mi); int screen_height = MI_HEIGHT (mi); GLfloat h = (GLfloat) screen_height / (GLfloat) screen_width; int x, y; int hits; pp->mouse_gear_id = 0; /* Poll mouse position */ { Window r, c; int rx, ry; unsigned int m; XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi), &r, &c, &rx, &ry, &x, &y, &m); } if (x < 0 || y < 0 || x > screen_width || y > screen_height) return; /* out of window */ /* Run OpenGL hit detector */ { GLint vp[4]; GLuint selbuf[512]; glSelectBuffer (sizeof(selbuf), selbuf); /* set up "select" mode */ glRenderMode (GL_SELECT); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glGetIntegerv (GL_VIEWPORT, vp); /* save old vp */ gluPickMatrix (x, vp[3]-y, 5, 5, vp); gluPerspective (30.0, 1/h, 1.0, 100.0); /* must match reshape_pinion() */ glMatrixMode (GL_MODELVIEW); draw_gears (mi); /* render into "select" buffer */ glMatrixMode (GL_PROJECTION); /* restore old vp */ glPopMatrix (); glMatrixMode (GL_MODELVIEW); glFlush(); hits = glRenderMode (GL_RENDER); /* done selecting */ if (hits > 0) { int i; GLuint name_count = 0; GLuint *p = (GLuint *) selbuf; GLuint *pnames = 0; GLuint min_z = ~0; for (i = 0; i < hits; i++) { int names = *p++; if (*p < min_z) /* find match closest to screen */ { name_count = names; min_z = *p; pnames = p+2; } p += names+2; } if (name_count > 0) /* take first hit */ pp->mouse_gear_id = pnames[0]; } } }
static struct gears * gears_create(struct display *display) { const int width = 450, height = 500; struct gears *gears; int i; gears = malloc(sizeof *gears); memset(gears, 0, sizeof *gears); gears->d = display; gears->window = window_create(display, "Wayland Gears", width, height); gears->display = display_get_egl_display(gears->d); if (gears->display == NULL) die("failed to create egl display\n"); eglBindAPI(EGL_OPENGL_API); gears->context = eglCreateContext(gears->display, NULL, EGL_NO_CONTEXT, NULL); if (gears->context == NULL) die("failed to create context\n"); if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context)) die("faile to make context current\n"); glGenFramebuffers(1, &gears->fbo); glBindFramebuffer(GL_FRAMEBUFFER_EXT, gears->fbo); glGenRenderbuffers(2, gears->color_rbo); glGenRenderbuffers(1, &gears->depth_rbo); glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, gears->depth_rbo); for (i = 0; i < 3; i++) { gears->gear_list[i] = glGenLists(1); glNewList(gears->gear_list[i], GL_COMPILE); make_gear(&gear_templates[i]); glEndList(); } glEnable(GL_NORMALIZE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0); glMatrixMode(GL_MODELVIEW); glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glClearColor(0, 0, 0, 0.92); window_set_user_data(gears->window, gears); window_set_resize_handler(gears->window, resize_handler); window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler); window_set_redraw_handler(gears->window, redraw_handler); draw_gears(gears); wl_display_frame_callback(display_get_display(gears->d), frame_callback, gears); return gears; }