Re: [gtk-list] Re: Using Mesa (openGL) with GTK



On Tue, 4 Nov 1997, Ivo Clarysse wrote:

> On Sun, 19 Oct 1997, Bj|rn Augustsson wrote:
> 
> > Juergen A. Erhard (jae@laden.ilk.de) wrote:
> > >It works for me after changing dbuf in gui_init to start with GL_RGBA
> > >and put the GLX_DOUBLEBUFFER at the end. Took me a couple minutes, and
> > >comparing with glxdemo.c in Mesa 2.3...
> > 
> > I also inserted GLX_RGBA, but doing just that that doesn't work well at
> > all, since the toplevel widget gets the default visual (In my case 
> > PseudoColor 8), and then the program tries to attach the TrueColor 24
> > visualled glarea widget to it.
> > 
> > The results are some pretty nasty kernel messages about failed asserts
> > and the GL rendering seems to be in black&white. (not grayscale, B&W)
> > 
> > This should really be possible to do, as it seems there is an OpenGL
> > widget for motif that can do it. (As seen in Mark Kilgards excellent
> > article from the X Journal, which can be found at
> > http://www.sgi.com/Technology/openGL/mjk.motif/  )
> > I don't know how though.

OK, I played around a bit, and I think I've got it.  The following
code works both on my Linux box (8-bit display) using Mesa, as
on a SGI box with 32-bit display and true OpenGL.  It only uses a
TrueColor visual for the OpenGL stuff, the rest is in whatever
visual GTK decides it wants.  (I must say, the gtk_widget_{push|pop}_visual
semantics are not very intuitive, it doesn't really 'push' the
argument, but pushes the current value and replaces it with the
argument).

Instead of using 'gtk_preview_get_visual', I use 'glXChooseVisual'.  
The gtk_preview_get_visual returns (AFAIK) a visual which gtk_preview
would like to use should it be created.  Mostly this is something
with 24-bit color.  On my SGI box, however, it returned a 24-bit color
visual, but not one which SGI's OpenGL is happy to render into. 

Anyway, here goes:

 ----8<------8<------8<------------

/*
 * glgtk.c
 *
 * Release: 971104-2
 *
 * Displays a rotating triangle with Open/GL | Mesa
 *
 */

#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>    /* A clean way to get to GDK's private parts */
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glu.h>

int redraw_needed=TRUE;

Display *dpy=NULL;
GLXContext glx_context;

GLfloat cam_xspin=0.0;
GLfloat cam_yspin=0.0;
GLfloat cam_zspin=0.0;
GLfloat cam_xpos=0.0;
GLfloat cam_ypos=0.0;
GLfloat cam_zpos=-4.0;

GtkWidget *glarea;

void object_redraw();

gint timer_callback(gpointer data)
{
 cam_zspin+=4;
 cam_xspin+=1;
 redraw_needed=TRUE;
 object_redraw();  /* Redraw object if needed */
 return(TRUE);
}

/* Define model in displaylist */
void            object_define()
{
  glNewList(1, GL_COMPILE_AND_EXECUTE);
  glClear(GL_COLOR_BUFFER_BIT);

  glBegin(GL_LINE_LOOP);
  glVertex3f(-1, 0, 0);
  glVertex3f( 0, -1, 0);
  glVertex3f( 1, -1, 0);
  glEnd();
  
  glEndList();
}


void object_redraw()
{
static int list_inited=FALSE;

  if (!redraw_needed) return;

  glXMakeCurrent(dpy,GDK_WINDOW_XWINDOW(glarea->window),glx_context);
  glShadeModel(GL_FLAT);
  glClearColor(0.0,0.0,0.0,0.0);
  glColor3f(1.0, 1.0, 1.0);
  glLineWidth(1.0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glTranslatef(cam_xpos, cam_ypos, cam_zpos);
  glRotatef(cam_xspin, 1.0, 0.0, 0.0);        /* rotate modelmatrix */
  glRotatef(cam_yspin, 0.0, 1.0, 0.0);        /* rotate modelmatrix */
  glRotatef(cam_zspin, 0.0, 0.0, 1.0);        /* rotate modelmatrix */

  if (list_inited) glCallList(1);
  else { 
    object_define(); 
    list_inited=TRUE; 
  }

  glFlush();
  glXSwapBuffers(dpy,GDK_WINDOW_XWINDOW(glarea->window));
  redraw_needed=FALSE;
}


/*
 * Callback function for 'Quit' button
 *
 */
void quit_button(GtkWidget *widget, gpointer *data)
{
  gtk_main_quit();
}

/*
 * Callback for GTK events in glarea 
 *
 */
gint glarea_events(GtkWidget *area, GdkEvent *event)
{
GdkEventConfigure *configevent;

  switch (event->type) {
    case GDK_EXPOSE:
      redraw_needed=TRUE;
      object_redraw();
      break;

    case GDK_CONFIGURE:  /* aka Resize */
      redraw_needed=TRUE;
      configevent=(GdkEventConfigure *)event;
    
      /* Resize OpenGL context in glarea */
      glMatrixMode(GL_PROJECTION);   
      glLoadIdentity();             
      glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
      glViewport(0, 0, configevent->width, configevent->height); 
      glMatrixMode(GL_MODELVIEW);       
      break;

    default:
      break;
    }
  return (FALSE);
}


void gui_init()
{
  gint TimerTag;
  GtkWidget *appwindow, *vbox, *button;
  XVisualInfo *vi;
  int dbuf[] = {GLX_RGBA,GLX_RED_SIZE,1,GLX_GREEN_SIZE,1,
                GLX_BLUE_SIZE,1,GLX_DOUBLEBUFFER,None};

  /* Look for a visual that OpenGL is happy with.. */
  dpy=GDK_DISPLAY();
  vi=glXChooseVisual(dpy,DefaultScreen(dpy),dbuf);
  if (vi==NULL) { fprintf(stderr,"ERROR: Could not find a visual OpenGL likes.\n"); exit(-1); }
  if (vi->class != TrueColor) printf("Non-TrueColor visual selected\n"); 
  printf("Selected OpenGL visual = 0x%x\n",(unsigned int)(vi->visualid));


  /* Define GTK's window */

  appwindow=gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title(GTK_WINDOW(appwindow), "GL-GTK Test");

  vbox=gtk_vbox_new(FALSE,0);

  /* Upper row */

  /* replace current colormap and visual by one OpenGL/Mesa is happy with */
  gtk_widget_push_colormap(
     gdk_colormap_new(gdkx_visual_get(vi->visualid),TRUE));
  gtk_widget_push_visual(gdkx_visual_get(vi->visualid));

  glarea = gtk_drawing_area_new();
  gtk_drawing_area_size(GTK_DRAWING_AREA(glarea),300,300);
  gtk_widget_set_events(glarea,GDK_EXPOSURE_MASK);
  gtk_signal_connect(GTK_OBJECT(glarea), "event", (GtkSignalFunc)glarea_events, NULL);
  gtk_box_pack_start(GTK_BOX(vbox), glarea, FALSE, FALSE, 0);
  gtk_widget_show(glarea);

  /* Now switch back to the original colormap and visual */

  gtk_widget_pop_visual();
  gtk_widget_pop_colormap();


  /* Lower row */

  button=gtk_button_new_with_label("Quit");
  gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(quit_button), NULL);
  gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
  gtk_widget_show(button);


  /* ** */
  gtk_widget_show(vbox);
  gtk_container_add(GTK_CONTAINER(appwindow),vbox);

  gtk_widget_show(appwindow);

  /* Initialize OpenGL */

  glx_context = glXCreateContext(dpy,vi,None,GL_TRUE);
  if (glx_context==NULL) { fprintf(stderr,"ERROR: Could not create context\n"); exit(-1); }

  /* Initialize OpenGL context for rendering */
  glXMakeCurrent(dpy,GDK_WINDOW_XWINDOW(glarea->window),glx_context);
  glShadeModel(GL_FLAT);
  glClearColor(0.0,0.0,0.0,0.0);
  glColor3f(1.0, 1.0, 1.0);
  glLineWidth(1.0);

 /* Attach callback to timer */
  TimerTag=gtk_timeout_add(50,timer_callback,NULL);

}


/**********************************
 *
 * Main function - delegate :)
 *
 **********************************/
int main(int argc, char *argv[])
{
  gtk_init (&argc, &argv);

  gui_init();

  gtk_main();

  return 0;
}
----8<------8<------8<------------

I don't know if making a specific OpenGL drawingarea widget is really
useful ?  It would only save you about four lines of code for every
(Open|Mesa)GL widget you'd use in your program. 

Soggie.

-----------------------------------------------------------------------
 Ivo Clarysse <soggie@riv.be>,                Riverland Research Group
 Research Assistant                        http://www.riv.be/research/
                                                      Excelsiorlaan 42
 http://www.riv.be/~soggie/me/                B-1930 Zaventem, Belgium



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