static void gtku_gl_drawing_area_unrealize (GtkWidget * widget) { GtkuGLDrawingArea * self = GTKU_GL_DRAWING_AREA (widget); GtkuGLDrawingAreaPrivate * priv = GTKU_GL_DRAWING_AREA_GET_PRIVATE (self); #ifdef USE_VBLANK if (priv->thread) { /* Set a flag and wait for the thread to end */ priv->quit_thread = 1; pthread_join (priv->thread, NULL); close (priv->pipe[0]); } if (priv->vblank_watch) g_source_remove (priv->vblank_watch); #endif if (priv->context) glXDestroyContext (priv->dpy, priv->context); if (priv->visual) XFree (priv->visual); priv->dpy = NULL; priv->visual = NULL; priv->context = NULL; #ifdef USE_VBLANK priv->vblank_watch = 0; priv->pipe[0] = -1; priv->thread = 0; priv->quit_thread = 0; priv->swap_requested = 0; #endif /* chain up */ GTK_WIDGET_CLASS (gtku_gl_drawing_area_parent_class)->unrealize (widget); }
GtkWidget * gtku_gl_drawing_area_new (gboolean vblank_sync) { GObject * object = g_object_new (GTKU_TYPE_GL_DRAWING_AREA, NULL); GtkuGLDrawingArea * self = GTKU_GL_DRAWING_AREA (object); self->vblank_sync = vblank_sync; return GTK_WIDGET (object); }
static void gtku_gl_drawing_area_size_allocate (GtkWidget * widget, GtkAllocation * allocation) { GtkuGLDrawingArea * self = GTKU_GL_DRAWING_AREA (widget); /* chain up */ GTK_WIDGET_CLASS (gtku_gl_drawing_area_parent_class)->size_allocate (widget, allocation); /* Resize the OpenGL area to match the allocation size. */ if (gtku_gl_drawing_area_set_context (self) == 0) glViewport (0, 0, allocation->width, allocation->height); }
/* Called when the pipe has data on it, as written by the vblank-monitoring * thread. */ static gboolean swap_func (GIOChannel * source, GIOCondition cond, gpointer data) { GtkWidget * widget = GTK_WIDGET (data); GtkuGLDrawingArea * self = GTKU_GL_DRAWING_AREA (data); GtkuGLDrawingAreaPrivate * priv = GTKU_GL_DRAWING_AREA_GET_PRIVATE (self); if (priv->swap_requested) { if (gtku_gl_drawing_area_set_context (self) == 0) glXSwapBuffers (priv->dpy, GDK_WINDOW_XID (widget->window)); priv->swap_requested = 0; } /* Clear out the pipe of vblank events */ char buf[32]; while (1) { int num = read (priv->pipe[0], buf, sizeof (buf)); if (num <= 0) break; } return TRUE; }
static void gtku_gl_drawing_area_realize (GtkWidget * widget) { GtkuGLDrawingArea * self = GTKU_GL_DRAWING_AREA (widget); GtkuGLDrawingAreaPrivate * priv = GTKU_GL_DRAWING_AREA_GET_PRIVATE (self); /* chain up */ GTK_WIDGET_CLASS (gtku_gl_drawing_area_parent_class)->realize (widget); priv->dpy = GDK_WINDOW_XDISPLAY(widget->window); #if 0 priv->visual = glXChooseVisual (priv->dpy, GDK_SCREEN_XNUMBER (gdk_drawable_get_screen (GDK_DRAWABLE (widget->window))), //DefaultScreen (priv->dpy), attr_list); #endif GdkDrawable * draw = GDK_DRAWABLE (widget->window); int screen = GDK_SCREEN_XNUMBER (gdk_drawable_get_screen (draw)); XVisualInfo vinfo_template = { .visualid = XVisualIDFromVisual (gdk_x11_visual_get_xvisual ( gdk_drawable_get_visual (draw))), .screen = screen, .depth = gdk_drawable_get_depth (draw), }; int nitems; fprintf (stderr, "Using X Visual 0x%x\n", (unsigned int) vinfo_template.visualid); priv->visual = XGetVisualInfo (priv->dpy, VisualIDMask | VisualScreenMask | VisualDepthMask, &vinfo_template, &nitems); if (priv->visual == NULL) { g_warning ("Failed to find GLX visual\n"); return; } if (nitems != 1) fprintf (stderr, "Warning: more than one matching X visual found\n"); priv->context = glXCreateContext (priv->dpy, priv->visual, 0, GL_TRUE); if (!priv->context) { g_warning ("Failed to get GLX context\n"); XFree (priv->visual); priv->visual = NULL; return; } if (!glXMakeCurrent (priv->dpy, GDK_WINDOW_XID (widget->window), priv->context)) { g_warning ("Could not make GLX context current\n"); return; } /* If the user doesn't want vblank sync, we are done */ if (!self->vblank_sync) return; /* Check for the presence of the video_sync extension */ if (!is_glx_extension_present (priv->dpy, screen, "GLX_SGI_video_sync")) { self->vblank_sync = 0; fprintf (stderr, "Video sync functions not found, disabling...\n"); return; } #ifdef USE_VBLANK /* Below we create a new thread to monitor the vblank. We will * signal back to this thread by writing to a file descriptor * when each vblank occurs. */ /* TODO: check extension list */ GetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC) glXGetProcAddressARB ( (unsigned char *)"glXGetVideoSyncSGI"); WaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC) glXGetProcAddressARB ( (unsigned char *)"glXWaitVideoSyncSGI"); if (!GetVideoSyncSGI || !WaitVideoSyncSGI) { self->vblank_sync = 0; fprintf (stderr, "Video sync functions not found, disabling...\n"); return; } unsigned int count = 0; if (GetVideoSyncSGI (&count) != 0) { self->vblank_sync = 0; fprintf (stderr, "Video sync counter failed, disabling...\n"); return; } int pp = pipe (priv->pipe); assert (pp >= 0); fcntl (priv->pipe[0], F_SETFL, O_NONBLOCK); if (pthread_create (&priv->thread, NULL, swap_thread, priv) != 0) { self->vblank_sync = 0; fprintf (stderr, "Video sync thread creation failed, disabling...\n"); return; } GIOChannel * chan = g_io_channel_unix_new (priv->pipe[0]); priv->vblank_watch = g_io_add_watch (chan, G_IO_IN, swap_func, self); g_io_channel_unref (chan); #endif }
static void on_image (const lcm_recv_buf_t *rbuf, const char *channel, const lcmtypes_image_t *msg, void *user_data) { RendererCamThumb *self = (RendererCamThumb*) user_data; if (! self->renderer.enabled) return; cam_renderer_t *cr = g_hash_table_lookup (self->cam_handlers, channel); if (!cr) { cr = (cam_renderer_t*) calloc (1, sizeof (cam_renderer_t)); cr->renderer = self; cr->render_place = 0; cr->channel = strdup (channel); g_hash_table_replace (self->cam_handlers, cr->channel, cr); } if (! cr->msg_received) { cr->gl_area = GTKU_GL_DRAWING_AREA (gtku_gl_drawing_area_new (FALSE)); cr->pw = GTKU_PARAM_WIDGET (gtku_param_widget_new ()); gtku_param_widget_add_enum (cr->pw, PARAM_RENDER_IN, 0, cr->render_place, "Here", RENDER_IN_WIDGET, "Top Left", RENDER_IN_TOP_LEFT, "Top Cent.", RENDER_IN_TOP_CENTER, "Top Right", RENDER_IN_TOP_RIGHT, "Bot. Left", RENDER_IN_BOTTOM_LEFT, "Bot. Cent.", RENDER_IN_BOTTOM_CENTER, "Bot. Right", RENDER_IN_BOTTOM_RIGHT, NULL); cr->expander = gtk_expander_new (channel); gtk_box_pack_start (GTK_BOX (self->renderer.widget), cr->expander, TRUE, TRUE, 0); GtkWidget *vbox = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (cr->expander), vbox); gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (cr->pw), TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (cr->gl_area), TRUE, TRUE, 0); g_signal_connect (G_OBJECT (cr->gl_area), "size-allocate", G_CALLBACK (on_gl_area_size), cr); cr->width = msg->width; cr->height = msg->height; gtk_widget_show_all (GTK_WIDGET (cr->expander)); gtk_expander_set_expanded (GTK_EXPANDER (cr->expander), cr->expanded); if (cr->render_place == RENDER_IN_WIDGET) { gtk_widget_show (GTK_WIDGET (cr->gl_area)); } else { gtk_widget_hide (GTK_WIDGET (cr->gl_area)); } g_signal_connect (G_OBJECT (cr->pw), "changed", G_CALLBACK (on_cam_renderer_param_widget_changed), cr); g_signal_connect (G_OBJECT (cr->gl_area), "expose-event", G_CALLBACK (on_gl_area_expose), cr); g_signal_connect (G_OBJECT (cr->expander), "notify::expanded", G_CALLBACK (on_expander_expanded), cr); cr->texture = NULL; cr->last_image = NULL; cr->renderer = self; cr->uncompressed_buffer_size = msg->width * msg->height * 3; cr->uncompresed_buffer = (uint8_t*) malloc (cr->uncompressed_buffer_size); cr->msg_received = 1; } if (cr->last_image) { lcmtypes_image_t_destroy (cr->last_image); } cr->last_image = lcmtypes_image_t_copy (msg); cr->is_uploaded = 0; switch (gtku_param_widget_get_enum (cr->pw, PARAM_RENDER_IN)) { case RENDER_IN_WIDGET: if (gtk_expander_get_expanded (GTK_EXPANDER (cr->expander))) gtku_gl_drawing_area_invalidate (cr->gl_area); default: viewer_request_redraw (self->viewer); break; } }
static void viewer_init (Viewer *viewer) { viewer->renderers = g_ptr_array_new(); viewer->renderers_sorted = g_ptr_array_new(); viewer->renderers_sorted_with_controls = g_ptr_array_new(); viewer->event_handlers = g_ptr_array_new(); viewer->event_handlers_sorted = g_ptr_array_new(); viewer->modes = g_ptr_array_new(); viewer->prettier_flag = (getenv("DGC_VIEWER_PRETTIER") != NULL && atoi(getenv("DGC_VIEWER_PRETTIER"))>0);; printf("DGC_VIEWER_PRETTIER: %d\n", viewer->prettier_flag); viewer->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(viewer->window), "Viewer"); gtk_window_set_resizable(GTK_WINDOW(viewer->window), TRUE); gtk_window_set_default_size(GTK_WINDOW(viewer->window), 800, 540); GtkWidget *vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(viewer->window), vbox); make_menus(viewer, vbox); viewer->tips = gtk_tooltips_new (); make_toolbar(viewer, vbox); GtkWidget *hpaned = gtk_hpaned_new(); gtk_box_pack_start(GTK_BOX(vbox), hpaned, TRUE, TRUE, 0); GtkWidget *gl_box = gtk_event_box_new(); gtk_paned_pack1(GTK_PANED(hpaned), gl_box, TRUE, TRUE); GtkWidget *controls_align = gtk_alignment_new(.5, .5, 1, 1); gtk_paned_pack2(GTK_PANED(hpaned), controls_align, FALSE, TRUE); gtk_paned_set_position(GTK_PANED(hpaned), 560); GtkWidget *controls_scroll = gtk_scrolled_window_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(controls_align), controls_scroll); GtkWidget *controls_view = gtk_viewport_new(NULL, NULL); gtk_container_add(GTK_CONTAINER(controls_scroll), controls_view); viewer->controls_box = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(controls_view), viewer->controls_box); viewer->status_bar = gtk_statusbar_new(); gtk_box_pack_start(GTK_BOX(vbox), viewer->status_bar, FALSE, FALSE, 0); viewer_set_status_bar_message(viewer, "Ready"); // create the aspect area to maintain a 1:1 aspect ratio viewer->gl_area = GTKU_GL_DRAWING_AREA (gtku_gl_drawing_area_new (FALSE)); gtk_widget_set_events (GTK_WIDGET (viewer->gl_area), GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); gtk_container_add (GTK_CONTAINER (gl_box), GTK_WIDGET (viewer->gl_area)); gtk_widget_show (GTK_WIDGET (viewer->gl_area)); g_signal_connect (G_OBJECT (viewer->gl_area), "configure-event", G_CALLBACK (on_gl_configure), viewer); g_signal_connect (G_OBJECT (viewer->gl_area), "expose-event", G_CALLBACK (on_gl_expose), viewer); g_signal_connect (G_OBJECT (viewer->gl_area), "button-press-event", G_CALLBACK (on_button_press), viewer); g_signal_connect (G_OBJECT (viewer->gl_area), "button-release-event", G_CALLBACK (on_button_release), viewer); g_signal_connect (G_OBJECT (viewer->gl_area), "motion-notify-event", G_CALLBACK (on_motion_notify), viewer); g_signal_connect (G_OBJECT (viewer->gl_area), "scroll-event", G_CALLBACK (on_scroll_notify), viewer); g_signal_connect (G_OBJECT (viewer->window), "key_press_event", G_CALLBACK (on_main_window_key_press_event), viewer); g_signal_connect (G_OBJECT (viewer->window), "delete_event", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect (G_OBJECT (viewer->window), "delete_event", G_CALLBACK (gtk_widget_hide_on_delete), NULL); g_signal_connect (G_OBJECT (viewer->window), "destroy_event", G_CALLBACK(gtk_main_quit), NULL); //////////////////////////////////////////////////////////////////// // Create plugins menu // plugins will be inserted here as add_plugin is called gtk_widget_show_all(viewer->window); DefaultViewHandler *dvh = default_view_handler_new(viewer); viewer->default_view_handler = &dvh->vhandler; viewer_request_redraw(viewer); }