Re: pthreads + drawing area = expose event fails



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 mailing list
gtk-list gnome org
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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]