I tried putting gdk_threads_enter() & leave() in appropriate places to no avail. So here's more code:
int main (int argc, char *argv[]) { GtkWidget *mainwindow; gint major, minor; sigset_t sig_to_block; int i, j;
/* init glib threads stuff for gtk */ g_thread_init(NULL); gdk_threads_init();
/* Setup the signals to block, threads will inherit this mask... */
sigemptyset(&sig_to_block);
/* Block SIGPIPE so the write to sockets will not get us when socket closed */
sigaddset(&sig_to_block, SIGPIPE);
/* Block SIG INT,TERM,SEGV so we can catch to close down and exit... */
sigaddset(&sig_to_block, SIGINT);
sigaddset(&sig_to_block, SIGTERM);
sigaddset(&sig_to_block, SIGSEGV);
pthread_sigmask(SIG_BLOCK, &sig_to_block, NULL);
gtk_set_locale (); gtk_init (&argc, &argv); gtk_gl_init (&argc, &argv); gdk_gl_query_version (&major, &minor); g_print ("\nOpenGL extension version - %d.%d\n", major, minor);
mainwindow = create_mainwindow (); gtk_widget_show (mainwindow);
gdk_threads_enter(); gtk_main (); gdk_threads_leave(); return 0; }
GtkWidget* create_viewwindow (void) { GtkWidget *viewwindow; GtkWidget *vbox4; GtkWidget *menubar3; GtkWidget *menuitem9; GtkWidget *menuitem9_menu; GtkWidget *separatormenuitem3; GtkWidget *exit2; GtkWidget *drawing_area; GtkAccelGroup *accel_group; glargs *garg; . . . if ((garg = (glargs *) calloc(1, sizeof(glargs))) == NULL) { printf("Cannot calloc gl args.\n"); return NULL; } /* Try double-buffered visual */ garg->glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB | GDK_GL_MODE_DEPTH | GDK_GL_MODE_DOUBLE); garg->drawing_area = gtk_drawing_area_new(); gtk_widget_set_size_request(garg->drawing_area, 300, 300); /* Set OpenGL-capability to the widget. */ gtk_widget_set_gl_capability(garg->drawing_area, garg->glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE); gtk_widget_add_events(garg->drawing_area, GDK_BUTTON1_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_VISIBILITY_NOTIFY_MASK);
g_signal_connect_after(G_OBJECT(garg->drawing_area), "realize", G_CALLBACK(init), NULL); g_signal_connect(G_OBJECT(garg->drawing_area), "configure_event", G_CALLBACK(configure_event), NULL); g_signal_connect(G_OBJECT(garg->drawing_area), "expose_event", G_CALLBACK(expose_event), &garg); gtk_box_pack_start(GTK_BOX(vbox4), garg->drawing_area, TRUE, TRUE, 0); gtk_widget_show(garg->drawing_area);
gtk_window_add_accel_group (GTK_WINDOW(viewwindow), accel_group);
return viewwindow; }
int create_view_wrapper(viewthreadargs *vtargs) { vtargs->viewwindow = create_viewwindow(); gtk_container_set_reallocate_redraws(GTK_CONTAINER(vtargs->viewwindow), TRUE); gtk_widget_show(vtargs->viewwindow); }
int on_create_view_activate (GtkMenuItem *menuitem, gpointer user_data) { pthread_t t1; struct sched_param param1; viewthreadargs *vtargs; GError *error = NULL;
if ((vtargs = (viewthreadargs *) calloc(1, sizeof(viewthreadargs)))
== NULL) {
printf(" on_create_view_activate: Cannot calloc view window thread info.\n");
return -1;
}
if ((pthread_create(&t1, NULL, (void *) create_view_wrapper, vtargs)) != 0) { printf(" Problem pthread_create\n"); return -1; }
return 1; }
void init(GtkWidget *widget, gpointer data) { GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); printf("init; values: %x %x %x\n", &widget, &glcontext, &gldrawable); fflush(stdout);
static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; /*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) { return; }
glLightfv (GL_LIGHT0, GL_POSITION, pos); glEnable (GL_CULL_FACE); glEnable (GL_LIGHTING); glEnable (GL_LIGHT0); glEnable (GL_DEPTH_TEST);
glEnable (GL_NORMALIZE);
report_gl_version();
gdk_gl_drawable_gl_end (gldrawable); }
gboolean configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); printf("configure_event: values: %x %x %x\n", &widget, &glcontext, &gldrawable);fflush(stdout);
GLfloat w = widget->allocation.width; GLfloat h = widget->allocation.height; GLfloat aspect;
/*** OpenGL BEGIN ***/ if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext)) { return FALSE; }
glViewport (0, 0, w, h);
glMatrixMode (GL_PROJECTION); glLoadIdentity (); if (w > h) { aspect = w / h; glFrustum (-aspect, aspect, -1.0, 1.0, 2.0, 60.0); } else { aspect = h / w; glFrustum (-1.0, 1.0, -aspect, aspect, 2.0, 60.0); }
glMatrixMode (GL_MODELVIEW);
report_gl_version();
gdk_gl_drawable_gl_end (gldrawable); /*** OpenGL END ***/
return TRUE; }
gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { glargs *g1 = (glargs *) data; GdkGLContext *glcontext = gtk_widget_get_gl_context(widget); GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable(widget); GdkDrawable *drawable;
/*** OpenGL BEGIN ***/ printf("expose_event: values: %x %x %x\n", &widget, &glcontext, &gldrawable);fflush(stdout); printf("expose_event: values: %x %x %x\n", &g1->drawing_area, &g1->glcontext, &g1->gldrawable);fflush(stdout);
drawable = g1->drawing_area->window;
gdk_draw_rectangle(drawable, g1->drawing_area->style->white_gc, TRUE, 0, 0, g1->drawing_area->allocation.width, g1->drawing_area->allocation.height); /* if (!gdk_gl_drawable_gl_begin(g1->gldrawable, g1->glcontext)) { printf("expose_event: didn't get it :P\n"); fflush(stdout); report_gl_version(); return FALSE; } printf("expose_event: got it! continuing...\n"); fflush(stdout);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (gdk_gl_drawable_is_double_buffered (g1->gldrawable)) gdk_gl_drawable_swap_buffers (g1->gldrawable); else glFlush ();
gdk_gl_drawable_gl_end (g1->gldrawable); /*** OpenGL END ***/
return TRUE; }
Paul Davis wrote:
I'm trying to write an app that lets me open multiple pthreaded windows and do OpenGL in them using the GtkGLExt. Unfortunately I'm running into a problem getting the drawable in my expose event.
you haven't posted much code.
the golden rule of X programming (with *any* toolkit) is:
use only 1 thread to make calls that resolve to Xlib calls
if you don't want to do this, then you have to use mutexes to protect each and every call to any function that might ever make a call to Xlib. g_threads_enter() and g_threads_leave() are your GTK-related friends here. See the FAQ.
--p _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list
-- ------------------------------------------------------------------------ Ray Clouse STICS Lab ray.clouse AT boeing.com Don't fear the penguins. clouse AT rayclouse.org _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list